天天看點

Java -- 每日一問:一個線程兩次調用start()方法會出現什麼情況?

Java -- 每日一問:一個線程兩次調用start()方法會出現什麼情況?

典型回答

Java 的線程是不允許啟動兩次的,第二次調用必然會抛出 IllegalThreadStateException,這是一種運作時異常,多次調用 start 被認為是程式設計錯誤。

關于線程生命周期的不同狀态,在 Java 5 以後,線程狀态被明确定義在其公共内部枚舉類型 java.lang.Thread.State 中,分别是:

  • 建立(NEW),表示線程被建立出來還沒真正啟動的狀态,可以認為它是個 Java 内部狀态。
  • 就緒(RUNNABLE),表示該線程已經在 JVM 中執行,當然由于執行需要計算資源,它可能是正在運作,也可能還在等待系統配置設定給它 CPU 片段,在就緒隊列裡面排隊。

在其他一些分析中,會額外區分一種狀态 RUNNING,但是從 Java API 的角度,并不能表示出來。

  • 阻塞(BLOCKED),這個狀态和我們前面兩講介紹的同步非常相關,阻塞表示線程在等待 Monitor lock。比如,線程試圖通過 synchronized 去擷取某個鎖,但是其他線程已經獨占了,那麼目前線程就會處于阻塞狀态。
  • 等待(WAITING),表示正在等待其他線程采取某些操作。一個常見的場景是類似生産者消費者模式,發現任務條件尚未滿足,就讓目前消費者線程等待(wait),另外的生産者線程去準備任務資料,然後通過類似 notify 等動作,通知消費線程可以繼續工作了。Thread.join() 也會令線程進入等待狀态。
  • 計時等待(TIMED_WAIT),其進入條件和等待狀态類似,但是調用的是存在逾時條件的方法,比如 wait 或 join 等方法的指定逾時版本,如下面示例:
public final native void wait(long timeout) throws InterruptedException;      
  • 終止(TERMINATED),不管是意外退出還是正常執行結束,線程已經完成使命,終止運作,也有人把這個狀态叫作死亡。