2013-08-07 80 views
2

我正在研究線程連接()方法,我碰到了stackoverflow上的ThreadJoinMethod後 。我修改了代碼來開發一個工作示例,我對 輸出感到困惑。代碼片段是。線程連接()方法輸出混淆

class JoinRunnable implements Runnable{ 

    public void run() { 
    for(int i =0 ; i < 4 ; i++){ 
     System.out.println(i); 
    } 
    } 
} 
public class TestJoin{ 
    public static void main(String[] args) throws InterruptedException { 
    JoinRunnable joinRunnable = new JoinRunnable(); 
    Thread t1 = new Thread(joinRunnable); 
    Thread t2 = new Thread(joinRunnable); 
    t1.start(); 
    t2.start(); 
    System.out.println("Currently running thread: " + Thread.currentThread().getName()); 
    t1.join(); 
    t2.join(); 
    System.out.println("I must wait"); 
    } 
} 

以下程序的輸出是: -

0 
1 
2 
3 
0 
1 
2 
3 
Currently running thread: main 
I must wait 

我在輸出困惑。當前線程將在t1 和t2上調用join後加入,但爲什麼在t1和t2 完成後語句"Currently Running Thread: main"正在打印?我在這裏錯過了一些重要的概念嗎?因爲main()會在 之後加入t1和t2之前的連接語句。有人可以詳細說明嗎?

+0

其他兩個線程是否可能在調用'Thread','System','out'等各個庫之前調用它們的過程來產生結果?測試,通過爲每個人輸出1到10000,然後通過篩選獲得樂趣。 – christopher

+2

在循環迭代中添加睡眠,您將看到不會得到相同的結果。 –

+0

完美,我剛剛添加睡眠現在正在運行的方法main被首先打印。所以輸出必須不同。萬分感謝。 – benz

回答

4

線程在您致電start()後啓動這意味着它可以在任何行之後開始,甚至可以在它之後的行之前完成。

1

這只是運行得太快。在這兩個線程中插入一個短暫的睡眠。

2

你正在解釋錯誤的方式。 join()方法導致main線程等待t1t2。因此main在完成t1t2之前不會退出。首先打印的內容完全是任意的,主要取決於線程的優先級。要設置預定義的行爲,您必須同步這些線程。

+0

我想你實際上把問題解釋錯了。 –

+0

但是,t1和t2不會進入運行狀態,並且此語句顯示「Currnetly running thread main」。是嗎? – benz

+0

@RohitJain再次閱讀,他說主線程將被連接(意味着它將等待)。 – user2550754

1

這裏是join()方法的描述:
Blocks the current Thread (Thread.currentThread()) until the receiver finishes its execution and dies.(從的javadoc)
事實上,你可能會阻止它正在等待T1 T2 &停止你的主線程。

+0

但是,t1和t2不會進入運行狀態,並且此語句顯示「Currnetly running thread main」。是嗎? – benz

+0

我認爲Peter Lawrey的評論與你的問題比我的更相關,我認爲你應該增加一些短暫的睡眠(如上所述),看t1和t2的過程是否在此之前完成。 – Sw4Tish

+0

謝謝@ Sw4Tish。我這樣做了,這次輸出不一樣。 – benz

2

System.out.println在基礎OutputStream實例上同步(至少在我的PC上的實現中)。每個println之間的時間間隔非常短,所以來自另一個線程的println不太可能有機會被執行。所以看起來你在println上有一定的順序(至少很有可能)。插入一些睡覺,讓循環數更高,你應該能夠觀察到不同的行爲。

+0

謝謝非常多的人。我在這裏理解了這個概念。 – benz

1

線程T1和T2開始,你的發言之前,完成了他們的工作

System.out.println("Currently running thread: " + Thread.currentThread().getName()); 

實際上可以產生上screen.So線程T1和T2的任何輸出都已經完成了他們的任務,主線程可以繼續作爲線程加入到它們的run()方法中。

如果你想學習和理解連接兩個線程的概念,請在運行方法的for循環中提供Thread.sleep(1000)。