一.線程通常有五種狀態:
- 新建狀態(New):新創建了一個線程對象。
- 就緒狀態(Runnable):線程對象創建后,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待 獲取CPU的使用權。
- 運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。
- 阻塞狀態(Blocked):阻塞狀態是線程因為某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,才有機會轉到運行狀態。
- 5.死亡狀態(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()的作用是等待線程對象銷毀。
注意:sleep()方法給其他線程運行機會時不考慮線程的優先級,因此會給低優先級的線程以運行的機會;yield()方法只會給相同優先級或更高優先級的線程以運行的機會
join的意思是會等到調用改join方法的線程執行完畢之后才會執行其他線程,舉例說明:
public static void main(String[] args) throws InterruptedException {
//開啟一個線程
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("我是新開副線程的執行");
//這個方法會先讓副線程沉睡1秒之后在執行,但是期間不會影響主線程的執行
Thread.sleep(1000L);
}
});
thread.start();//啟動線程
//這個方法會等副線程執行完成之后才會接下來執行主線程,會影響主線程的執行
thread.join();
System.out.println("我是主線程的執行");
}
如有違規,請聯系博主刪除,轉載請注明出處!原文鏈接