線程知識點小結
一、線程創建方式有兩種:繼承Thread類和實現Runnable接口
1、繼承Thread,需要重寫run方法,因為Thread類中的run方法什麽也沒有做。如果想開啟新線程,光創建線程對象是遠遠不夠的,只有執行線程對象的start()方法,才能在棧中開啟新線程,並執行run()方法。如果沒有調用start()方法,僅僅只是使用ThreadDemo 調用run()方法,跟一般對象調用函數沒有任何區別,不會開啟新的線程。
public class ThreadDemo extends Thread{
public void run(){
//線程任務區
}
}
2、實現Runnable接口,只是創建了線程任務,但是還需要創建線程對象。在創建線程對象時把線程任務對象作為參數,然後調用線程對象的start()方法,才能開啟線程,並調用線程任務的run()方法。
public class RunnableSub implements Runnable{
public void run(){
//線程任務區
}
}
二、線程的狀態
線程阻塞狀態(擁有CPU的執行資格,但是沒有CPU的執行權)
|sleep()時間過、調用notify()/notifyAll()方法
|
線程狀態創建-----------------------start()--------------------------- 線程運行中-----------wait()、sleep()-----------------------線程凍結狀態(釋放CPU的執行資格和執行權)
(擁有CPU執行資格和執行權)
|
|(調用stop()方法,此方法已經過時;或者線程任務已經執行完畢;使用標記)
線程銷毀
三、wait()與sleep()的區別
相同點:都是可以是線程處於凍結狀態
區別:1、wait()方法只能在同步代碼塊中使用,並且釋放CPU的執行權和執行資格;sleep()方法,可以在同步代碼塊中使用,也可以在同步代碼塊外部使用,如果在同步代碼塊中使用,不會釋放鎖,會釋放CPU的執行權和執行資格,等待時間已過,獲取CPU的執行權後會繼續執行。如果是在同步代碼塊外會釋放CPU的執行資格和執行權。
2、wait()方法需要被notify()/notifyAll()方法喚醒;sleep()方法時間已過就會從凍結狀態變為阻塞狀態。
四、同步代碼塊與同步函數的區別(同步代碼塊的區分就是按照鎖來區分的)
相同點:兩個都是為了保證線程安全。
區別:同步代碼塊使用synchronized(同步鎖){
//同步鎖是任意類的對象,因為Object類中包含監視器的方法,所以所有的類都具有監視器的方法。
//要處理共享數據的代碼
}
同步函數是在函數類型上,鎖是當前類的對象(this)
public synchronized void setName(name){
this.name=name;
}
五、判斷是否需要同步
1、是否包含共享數據(如果不包含共享數據,就不需要使用同步);
2、處理共享數據的代碼是否有多條。
六、解決線程安全問題的步驟
1、首先判斷是否需要同步;
2、run()方法中有循環;
七、線程模型
1、單一的生產者和消費者;
2、多生產者和多消費者;
八、線程組的概念
為了方便管理線程,如果線程都處於假死狀態時,可以使用線程調用interrupt()方法,強制關閉線程,如果有多個,就需要多次調用此方法;如果多個線程都在同一個線程組中,就可以使用線程組調用interrupt()方法,就相當於多個線程都調用了interrupt()方法。
九、前臺線程與守候線程的區別
直接創建的線程都是前臺線程,需要等待線程運行結束,線程才會正常關閉;
前臺線程可以通過調用方法,將前臺線程轉化為守候線程,如果前臺線程都運行完畢,守候線程就會自動關閉(不管有沒有運行完)。
十、線程的優先級
1-10級,數字越大優先級越高,默認優先級是5,主線程也是5
十一、join()方法,yelid()方法
如果在主線程中調用join()方法,主線程就會等待當前線程執行完畢以後,才會繼續執行;
該方法與sleep()類似,只是不能由用戶指定暫停多長時間,不會釋放鎖,在run()方法中使用Thread.yelid();
線程知識點小結