JavaSE 第十九天
Day19
----------------------------------------------------------------------------------
今天內容:
(1)執行緒的常用方法
(2)執行緒的同步機制
1.執行緒常用方法(重點)
static void sleep(long millis) - 用於讓當前正在執行的執行緒休眠引數指定的毫秒數。
- 1秒 = 1000毫秒 1毫秒 = 1000微秒 1微秒 = 1000納秒
int getPriority() - 用於獲取呼叫物件所代表執行緒的優先順序。
void setPriority(int newPriority) - 用於更改執行緒的優先順序為引數指定的數值。
- 優先順序越高的執行緒表示獲取時間片的機會越多,但不保證一定先執行。
void join() - 用於使得當前正在執行的執行緒等待呼叫物件所代表的執行緒終止。
void join(long millis) - 等待呼叫物件所代表執行緒的時間最長為引數指定的毫秒數。
boolean isDaemon() - 用於測試呼叫物件是否為守護執行緒。
void setDaemon(boolean on) - 用於將呼叫物件設定為守護執行緒。
- 該方法必須在呼叫start()方法前使用。
- 當所有非守護執行緒結束後,則守護執行緒隨之結束,Java虛擬機器也就結束。
2.執行緒的同步機制(重點、難點)
2.1 基本概念
當多個執行緒同時訪問同一種共享資源時,可能會造成資料的覆蓋等不一致性問題,此時就需要對執行緒之間進行協調和通訊,該方式就叫執行緒的同步機制。
如:
03年左右 存摺 銀行卡 對應同一個賬戶
2.2 解決方案
由程式可知:當兩個執行緒同時執行取款200元的操作時,導致最終的賬戶餘額不正確。
引發原因:當第一個執行緒取款後還沒來得及改變賬戶餘額,第二個執行緒就已經開始執行。
解決方案:將兩個執行緒取款操作的併發執行修改為序列執行即可。
帶來問題:執行效率比較低,因此應該儘量減少序列的範圍。
2.3 實現方式
在Java語言中使用synchronized關鍵字來實現同步/物件鎖的效果,來保證每個執行緒執行的原子性,具體使用方式如下:
(1)使用同步語句塊的方式實現,語法格式為:
synchronized(物件的引用){
編寫所有需要鎖定的語句塊;
}
(2)使用同步方法的方式實現,直接使用synchronized關鍵字修飾整個方法即可。
等價於 synchronized(this){}的方式。
2.4 實現原理
當多個執行緒同時啟動後則開始搶佔共享資源,若其中一個執行緒搶到共享資源則使用物件鎖將資源鎖定後使用,其它執行緒進入阻塞狀態,直到該執行緒執行完畢鎖定內容後釋放物件鎖,此時阻塞的執行緒又開始搶佔共享資源,搶到資源的執行緒繼續鎖定,搶不到的執行緒繼續等待。
2.5 死鎖的概念(瞭解)
執行緒一執行的程式碼:
public void run(){
synchronized(a){ //持有物件鎖a等待物件鎖b
synchronized(b){
...
}
}
}
執行緒二執行的程式碼:
public void run(){
synchronized(b){ //持有物件鎖b等待物件鎖a
synchronized(a){
...
}
}
}
注意:
在以後的開發中儘量不要使用同步語句塊的巢狀結構。
2.6 Object類中的常用方法
void wait() - 用於使得當前執行緒進入等待狀態,直到其它執行緒呼叫notify()/notifyAll()
void wait(long timeout) - 除了其它執行緒呼叫notify()/notifyAll()方法外,還有引數
指定的毫秒數過去了也可以解除等待狀態。
void notify() - 用於喚醒等待的任意單個執行緒。
void notifyAll() - 用於喚醒等待的所有執行緒。
作業:
1.複習和理解執行緒同步機制。
2.參考並編寫學生資訊管理系統的案例。
3.有餘力的同學自己編寫生產者消費者模型的案例。