1. 程式人生 > >Thread.join()和synchronized關鍵字的解釋

Thread.join()和synchronized關鍵字的解釋

time () 進入 else exc main 需要 ted 如果

理解了好長時間哇。。。

 1     public final synchronized void join(long millis)
 2     throws InterruptedException {
 3         long base = System.currentTimeMillis();
 4         long now = 0;
 5 
 6         if (millis < 0) {
 7             throw new IllegalArgumentException("timeout value is negative");
8 } 9 10 if (millis == 0) { 11 while (isAlive()) { 12 wait(0); 13 } 14 } else { 15 while (isAlive()) { 16 long delay = millis - now; 17 if (delay <= 0) { 18 break
; 19 } 20 wait(delay); 21 now = System.currentTimeMillis() - base; 22 } 23 } 24 }

Thread.join

問題1:為什麽能阻塞當前線程?

其實從源碼來說,光想做到阻塞,那個while(isAlive())就做到了。 那麽這兒也先當問題,為什麽還要wait呢?如果只為了阻塞的話。

可能吧: 其實作為多線程的環境,作為設計者,第一時間一定會想到wait,因為這樣肯定沒問題。

問題2:為什麽wait(0)運行的結果是main線程變成了waiting狀態?(其實很好理解,但是很容易誤解)

我把調用 t.join的過程都弄到main函數裏了,這樣清楚點。

    public static void main(String[] args) {
        ThreadTest t = new ThreadTest();
        t.start();
        synchronized (t){
            while (t.isAlive()){
                try {
                    t.wait(0);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
        System.out.println(Thread.currentThread().getName());
        System.out.println(i);
    }

因為join方法是個synchroniez方法,所以想要在任何線程裏調用,先獲取到t的對象再說,即上面那樣

然後t.wait(0) 很容易誤解成把線程t給wait了,其實不然。

對於main線程來說,線程t只是個同步對象。這一切的操作,都在main線程中。所以是把main線程,放到了同步對象t的等待隊列中。所以是main線程waiting狀態。

問題3:什麽時候把waiting的線程notify了?

Thread.exit()方法,調用了 group.threadTerminated方法,這個細看看吧,主要是remove(t); if (nthreads == 0) {notifyAll();}

synchronized幾種不同的加鎖位置,需要獲取的鎖(監視)對象

  • 指定加鎖對象:對給定對象加鎖,進入同步代碼前要獲得給定對象的鎖。 記住,wait()把線程放到該對象的等待隊列之後,會釋放該對象(鎖)。
  • 直接作用於實例方法:相當於對當前實例加鎖,進入同步代碼塊前需要獲得當前實例的鎖。就像上面那樣
  • 直接作用於靜態方法:相當於對當前類加鎖,進入同步代碼塊前要獲得當前類的鎖。

其實這幾種方式的本質是:synchronized可以作用於不同的地方,而這三種東西都可以作為同步對象(鎖)。

Thread.join()和synchronized關鍵字的解釋