2015-04-21 48 views
4

我看過之前的一些SO問題和文檔,但沒有找到我的迴應:這個線程可以活着,如何使用java.lang.Thread.join()方法

所以......

public class MyThread extends Thread { 
    public MyThread() { 
    this.setName("MyThread-" + System.currentTimeMillis()); 
    this.start(); 
    } 

    public MyThread(long millis) throws InterruptedException { 
    this.setName("MyThread-" + System.currentTimeMillis()); 
    this.join(millis); 
    this.start(); 
    } 

    @Override 
    public void run() { 
    System.out.println("I am running..."); 
    // This thread does not sleep... no Thread.sleep() in run method. 
    // Do some things like requesting a database 
    // Database response happens in less time that the timeout 
    } 
} 

public class MyClass { 

    public MyClass(){ 
    for (int i = 0; i < 5; i++) { 
     Thread t1 = new MyThread(); 
     t1.join(5000); 
     if (t1.isAlive()) { 
     System.out.println("I'm alive"); 
     // do some things 
     } else { 
     System.out.println("I'm not alive"); 
     } 

     Thread t2 = new MyThread(5000); 
     if (t2.isAlive()) { 
     System.out.println("I'm alive"); 
     // do some things 
     } else { 
     System.out.println("I'm not alive"); 
     } 

    } 
    } 
} 

看起來不可能,但t1之一可以活着嗎? t2怎麼樣? 發生了什麼,當我打電話join()start()

有關信息,我使用:

  • JVM:Java的熱點(TM)客戶端虛擬機(20.45-B01,混合模式,共享)
  • 的Java:版本1.6.0_45,供應商Sun微系統公司

更新閱讀一些您的回答後

如果我的理解,更好的實現將是這樣的:

public class MyThread extends Thread { 
    public MyThread() { 
    super("MyThread-" + System.currentTimeMillis()); 
    } 

    @Override 
    public void run() { 
    System.out.println("I am running..."); 
    // This thread does not sleep... no Thread.sleep() in run method. 
    // Do some things like requesting a database 
    // Database response happens in less time that the timeout 
    } 
} 

public class MyClass { 

    public MyClass(){ 
    for (int i = 0; i < 5; i++) { 
     Thread t1 = new MyThread(); 
     t1.start(); 
     t1.join(5000); 

     if (t1.isAlive()) { 
     System.out.println("I'm alive"); 
     // do some things 
     } else { 
     System.out.println("I'm not alive"); 
     } 
    } 
    } 
} 

這兩種看法都幫了我很多:https://stackoverflow.com/a/29775219/1312547https://stackoverflow.com/a/29775083/1312547

+7

兩個筆記,雖然他們沒有回答你的問題:首先,你爲什麼要在構造函數中啓動之前加入線程呢?其次,你實際上不應該從它的構造函數中啓動一個線程。原因有點微妙,但基本上一堆方便合理的線程保證會在窗口出現,如果你這樣做的話。你應該總是先構建它,然後啓動它。 – yshavit

+2

[建議實現Runnable而不是擴展線程](http://stackoverflow.com/questions/541487/implements-runnable-vs-extends-thread)。我建議你先在代碼中遵循多線程的良好實踐,然後重寫你的測試。 – m0skit0

+2

同上yshavit說:在構造函數中調用'this.start()'是_Bad Idea_。它可能允許新線程的run()方法查看處於未初始化狀態的Thread對象。將start()調用移動到MyClass()構造函數中。調用.start()之前調用.join()?您是否閱讀過文檔? –

回答

1

注意的是,雖然Thread.join(long)的(JDK 7)文件說

等待最多millis毫秒該線程終止。

它還繼續

此實現使用的this.wait電話空調上this.isAlive循環。

而且Thread.isAlive說:如果它已經開始,還沒有死

線程是活的。

所以你的代碼:

  • 當調用t1.isAlive(),它始終是false因爲你啓動線程(從構造函數)之後加入。
  • 當調用t2.isAlive(),這是大部分時間true因爲
    • 您啓動線程(在構造函數),其立即返回
    • 線程剛剛開始(在構造函數)
    • 之前加入

因此,要回答你的問題

看起來不可能,但t1之一可能還活着嗎?

對於t1沒有,只要等待時間超過了它需要它運行的時間更多。對於t2,

+0

'this.wait循環調用this.alive'意味着如果'isAlive()== false'那麼在我的情況下,線程會重新轉到「活」狀態,直到等待5秒鐘?這是否適用於Java v1.6? – Manu

+1

我不確定如何理解你的評論,但是如果'!isAlive()',那麼'join(...)'立即返回,不用等待。 Java 6中的行爲是相同的,但是文檔已經在Java 7中更新以反映這種行爲(循環在'isAlive()')上。 –

2

isAlive()文檔說:

一如果線程已經啓動並且尚未死亡,線程仍然有效。

join()文檔說:

等待最多millis毫秒爲這個線程死亡

因此,後加入()返回時,

  • 無論是線程已經死亡,並且isAlive()將是假的
  • 或線程尚未中斷,但延遲已過,isAlive()可能爲true。這是可能的,但是極不可能,因爲線程有5秒鐘的時間來完成打印到控制檯的簡單工作。
1

您的t1.isAlive()將永遠是錯誤的。您正在執行的線程需要毫秒運行。您打電話t1.join(5000),它將當前線程加入該線程,一旦它死亡。由於它的運行速度總是比5秒快,因此在它檢查是否存在時它總是死掉。

您的t2.isAlive()將始終爲真。在調用start方法之前,在t2線程上調用join的構造函數。由於在調用start方法之前線程總是死掉,所以在構造函數中的連接立即返回。然後允許開始被調用。儘管在線程中調用start並不意味着它立即執行。它只是將其標記爲可執行,並且線程調度程序將在未來某個時刻啓動它。由於您在構造函數後立即調用t2.isAlive(),它將始終爲真,因爲當前線程不會被換出。

1

隨着你的代碼,t1線程肯定會總是打印出「我還活着」,而t2,「我還活着」。

對於t2線程,很是怪異啓動線程之前調用this.join(...),因爲(作爲補充什麼@JB指出),該join() doc

此實現使用this.wait的環呼籲以此爲條件。

而且,由於線程尚未啓動,因此連接無效並立即返回。

但你的問題是什麼可以使t1活着。在run()方法中只需添加一個Thread.sleep(6000),您將看到該線程爲活動狀態。這意味着如果線程完成的任務(DB請求,...)長於join()中設置的超時,那麼答案是「是的,t1可以活着」。

+0

你是否建議:構造線程('Thread t = new Thread();'),然後啓動它('t.start();'),最後調用join('t.join(5000);') ?按這個順序?或者更好的是't.join(5000); t.start();'? – Manu

+1

在線程啓動之前加入沒有任何影響。 –

+1

我不知道你在做什麼,但正如所說的,當調用'this.join(5000); this.start();'在構造函數中,'join()'不會做任何事情。 –

相關問題