線程的幾種狀態以及sleep/wait/yield/join的區別

一.線程通常有五種狀態:

新建狀態(New):新創建了一個線程對象。

  • 就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待 獲取CPU的使用權。
  • 運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。
  • 阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。
  • 死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。

二.阻塞的情況分爲三種:

等待阻塞:運行的線程執行wait()方法,該線程會釋放佔用的所有資源,JVM會把該線程放入“等待池”中。進入這個狀態後,是不能自動喚醒的,必須依靠其他線程調用notify()或notifyAll()方法才能被喚醒,wait是object類的方法

  • 同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入“鎖池”中。
  • 其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。sleep是Thread類的方法。

三.Java中sleep,wait,yield,join的區別

  • sleep()方法
    在指定時間內讓當前正在執行的線程暫停執行,但不會釋放“鎖標誌”.不推薦使用.
    sleep()使當前線程進入阻塞狀態,在指定時間內不會執行。
  • wait()方法
    在其他線程調用對象的notify或notifyAll方法前,導致當前線程等待。線程會釋放掉它所佔有的“鎖標誌”,從而使別的線程有機會搶佔該鎖。
    當前線程必須擁有當前對象鎖。如果當前線程不是此鎖的擁有者,會拋出IllegalMonitorStateException異常。
    喚醒當前對象鎖的等待線程使用notify或notifyAll方法,也必須擁有相同的對象鎖,否則也會拋出IllegalMonitorStateException異常。
    waite()和notify()必須在synchronized函數或synchronized block中進行調用。如果在non-synchronized函數或non-synchronized block中進行調用,雖然能編譯通過,但在運行時會發生IllegalMonitorStateException的異常。
  • yield方法
    暫停當前正在執行的線程對象。
    yield()只是使當前線程重新回到可執行狀態,所以執行yield()的線程有可能在進入到可執行狀態後馬上又被執行。
    yield()只能使同優先級或更高優先級的線程有執行的機會。
    調用yield方法並不會讓線程進入阻塞狀態,而是讓線程重回就緒狀態,它只需要等待重新獲取CPU執行時間,這一點是和sleep方法不一樣的。
  • join方法
    等待該線程終止。
    等待調用join方法的線程結束,再繼續執行。如:t.join();//主要用於等待t線程運行結束,若無此句,main則會執行完畢,導致結果不可預測。
    在很多情況下,主線程創建並啓動了線程,如果子線程中藥進行大量耗時運算,主線程往往將早於子線程結束之前結束。這時,如果主線程想等待子線程執行完成之後再結束,比如子線程處理一個數據,主線程要取得這個數據中的值,就要用到join()方法了。方法join()的作用是等待線程對象銷
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章