2017年11月11日 星期六

Thread

Thread() 的constructor可以接受Runnable的instance,但是因為Thread有繼承Runnable,所以也可以放入Thread的constructor內

Thread method:
1. public void start()
  • 呼叫start()才會開始執行thread程序
2. public static void yield()


  • 讓目前執行中的thread回到Runnable的狀態,使其他priority相同的thread有機會被輪到,所 yield()可以促進相同priority的thread輪替。但不保證會讓想要的thread被選上!
3. public static void sleep(long millis) throws InterruptedException
  • sleep是一個static method,是一個class level的method,意即沒有一個thread可以叫另外一個thread sleep。假設在a thread執行時呼叫b.sleep(),此時其實還是a sleep(static method只影響目前的thread),雖然讓人誤解但是合法的
4. public final void join() throws InterruptedException
  • 功能:呼叫Join()的Thread需要等到被呼叫的完成才可繼續。Ex: main Thread呼叫t1.join(),意指t1需結束main Thread才能繼續執行。呼叫時必須處理 InterruptedException,因為要等
Object method:
1. public final void wait() throws InterruptedException
  • 必須要在synchronized block呼叫,且要拿到locker才有辦法呼叫wait()
  • 呼叫時必須處理 InterruptedException,因為要等
  • synchronized(anotherObject) { // 取得anotherObject的鎖 
    try {
      anotherObject.wait();
    // 執行緒釋放鎖並且等待
    // 為了繼續執行,執行緒需要鎖,
    // 所以它可能會被卡住,直到它取得鎖
    } catch(InterruptedException e){} }
    
    範例如上,表示一開始若拿到anotherObject的locker,就能夠進入try區塊,而anotherObject.wait()將會釋放anotherObject locker,直到等到有人呼叫notify()。若寫的是其他object.wait()則會有exception: IllegalMonitorStateExceptionObject 
  • wait裡若有帶parameter,表示最多等待時間。如下範例,最多等兩秒或是被notify()
  • synchronized(a){ // 執行緒取得a的鎖 
      a.wait(2000); 
    // 執行緒釋放鎖並等待通知 
    // 最多等待兩秒,便回到可執行的狀態
    // 執行緒取得鎖
    // 其他指令
    }

2. public final void notify()
  • 必須要在synchronized block呼叫,且要拿到locker才有辦法呼叫notify()
  • 呼叫此函式後,Thread鑰直到離開synchronized block才會釋放所持有的lock 
  • 只會隨機通知一個等到此locker的thread

3. public final void notifyAll()
  • 必須要在synchronized block呼叫,且要拿到locker才有辦法呼叫notifyAll()
  • 呼叫此函式後,Thread鑰直到離開synchronized block才會釋放所持有的lock 
  • 和notify()的差別是,會通知所有等待的此locker的thread
    Runnable method:
    1. void run()
    • 呼叫start()才會開始執行thread程序
    Synchronized:

    • 當有兩個執行指令不能被分割,稱為atomic operation,這時可用synchronized保證不會被打斷
    public class Test4 {
        private int a;
        private int b;
    
        public void set(int a, int b) { 
            synchronized (this){ // synchronized here is ok. Note that parameter must be an object
                this.a = a;
                this.b = b;
            }
        }
    
        public synchronized int read() { // synchronized here is ok
            return a + b;
        }
    
    }
    
    上述兩種synchronized寫法都可以
    注意locker一定要是一個object

    Thread-Safe:
    當一個class使用同步化保護資料時,會說這個class是thread-safe(如Vector, Hashtable, StringBuffer..),但只是針對這個class內的method做同步化,例如以下例子:

    if (names.size() > 0)
      return (String) names.remove(0);
    else
      return null;
    
    則假設此時有t1, t2兩個thread執行,t1和t2輪流檢查size都>0,也輪流移除element,第二個thread還是會遭遇錯誤的發生(null point)。因此使用thread-safe的class並不能保證讓自己寫的class變成thread-safe
    Static synchronized:
    • 如果是不同的instance,非static synchronized method並不會彼此卡住,因為這時候的locker是this
    • 如果是static synchronized method,同一個class的instance會卡住,因為這時候的locker是MyClass.class,也可以寫成Class.forName("MyClass")JVM會找出代表 MyClass的Class instance。
    • static synchronized method和非static synchronized method並不會彼此卡住。前者的locker是class instance,後者是this

    沒有留言:

    張貼留言