2014-10-07 51 views
0
class Lock implements Runnable{ 
    int i=0; 
    public synchronized void run(){ 
    for(i=0;i<10;i++){ 
     if(Thread.currentThread().getName().equals("t1") && i == 5) 
     {try { this.wait();} catch(InterruptedException ie){}} 
     System.out.print(Thread.currentThread().getName()+" "); 
     if(Thread.currentThread().getName().equals("t3") && i == 9) 
     this.notifyAll(); 
    } 
} 
} 
public class ThreadLock { 
public static void main(String[] args){ 
    Lock l = new Lock(); 
    Thread t1 = new Thread(l); 
    Thread t2 = new Thread(l); 
    Thread t3 = new Thread(l); 
    t1.setName("t1"); 
    t2.setName("t2"); 
    t3.setName("t3"); 
    t1.start(); 
    t2.start(); 
    t3.start(); 
} 
} 

輸出是: T1 T1 T1 T1 T1 T3 T3 T3 T3 T3 T3 T3 T3 T3 T3 T1 T2 T2 T2 T2 T2 T2 T2 T2 T2 T2線程沒有在Java notifyAll的後印刷一切

T1是調用notifyAll方法後不全部打印10次。 我跑了很多次,但每次t1只打印6次。 爲什麼t1沒有全部打印10次? 請儘快回覆

+0

即使您將'i'更改爲本地變量,該程序也不是_guaranteed_,因此總是會打印「t1」十次。理論上t3線程可以完成任務,並在t1任務調用wait()之前調用notifyAll()。如果發生這種情況,'wait()'調用將永遠不會返回。 – 2014-10-08 21:49:55

回答

2

i是一個實例變量。它由所有線程共享。它應該是一個局部變量。

當第一個線程被喚醒時,它重新獲得鎖定,打印其名稱,遞增i,並重新評估,如果i < 10。但由於其他線程已將i設置爲10,循環停止。

1

問題是您在線程之間共享相同索引i,因此當線程t3存在且t1被喚醒索引i將爲10並且線程t1中的for循環將退出。

0

嘗試調用每個線程後調用.join()以確保每個線程在程序退出前完成?

+0

任何活的非守護進程線程都應該阻止jvm終止,但當主返回時stdout可能會被關閉。 – tariksbl 2014-10-07 19:55:44

+0

Doh-我是其他人指出的共享。 – tariksbl 2014-10-07 19:57:54

0

而正確的答案已經被JB Nizet給,你可能想知道,爲什麼這隻會影響t1: 每個線程正在重置i,當運行方法(同步)被調用。

但是,當你返回t1的執行 - 它不會重置i,因爲線程已經啓動for -loop。

i | output 
    0 | t1 (FIRST iteration of t1 -> Setting i=0) 
    1 | t1 
    2 | t1 
    3 | t1 
    4 | t1 
    5 | t1 
    0 | t3 (FIRST iteration of t3 -> Setting i = 0) 
    1 | t3 
    2 | t3 
    3 | t3 
    4 | t3 
    5 | t3 
    6 | t3 
    7 | t3 
    8 | t3 
    9 | t3 
    0 | t2 (FIRST iteration of t2 -> Setting i = 0) 
    1 | t2 
    2 | t2 
    3 | t2 
    4 | t2 
    5 | t2 
    6 | t2 
    7 | t2 
    8 | t2 
    9 | t2 
    9 | t1 (t1 restored, but i=9 now. One more output, program done) 

注意:至少你所描述的輸出發生了什麼。我認爲t2也可能會在t3之前執行,導致不同的輸出。

+0

謝謝。我知道了。 '我'是在同步方法之外,所以現在我做了for循環的'我'局部變量。 'for(int i = 0; i <10; i ++)'。現在它的打印t1全部10次。 – pk1991 2014-10-08 02:32:37