第一章:Java多執行緒技能
使用多執行緒
- 實現多執行緒有兩種方式:繼承
Thread
類、實現Runnable
介面 Thread.java
中的start()
方法是非同步執行,thread.run
是同步;而且start()
方法的順序不代表執行緒啟動的順序,它是隨機的。- 在方法前加
synchronized
可以讓執行緒安全。
一些方法
currentThread()
返回程式碼段正在被哪個執行緒呼叫isAlive()
判斷當前執行緒是否處於活動狀態sleep()
讓執行緒休眠getID()
獲得執行緒的唯一標誌yield()
讓當前執行緒放棄cpu資源,但時間不確定
停止執行緒
方式:
- 使用退出標識,使執行緒正常退出,也就是當run方法完成後執行緒退出
- 使用interrupt方法中斷執行緒
第二種方式要注意:
interrupt()
例項方法,讓執行緒中斷,再用異常法檢測中斷使程式停止interrupted()
是靜態方法,測試當前執行緒是否已經是中斷狀態,執行後具有將狀態標誌清除為false的功能。isInterrupted()
是例項方法,測試Thread物件是否已經是中斷狀態,但不清除狀態標誌。- 如果在sleep狀態下停止某一執行緒,會進入catch語句(不需要判斷是否中斷),並且清除停止狀態,使它變為false.
執行緒的優先順序
getPriority()
檢視優先順序,setPriority()
設定優先順序,有1~10級
執行緒優先順序的特點:
- 繼承性: 如過執行緒A啟動執行緒B,則B和A優先順序一樣
- 規則性: CPU儘量傾向於把資源優先順序高的執行緒
- 隨機性: 優先順序不等同於執行順序,優先順序較高的不一定先執行完
守護執行緒
Java的執行緒分為兩種:User Thread(使用者執行緒)、Daemon Thread(守護執行緒)。
當最後一個非守護執行緒結束時,守護執行緒隨著JVM一同結束工作。Daemon作用是為其他執行緒提供便利服務,守護執行緒最典型的應用就是GC(垃圾回收器),它就是一個很稱職的守護者。
第二章:物件及變數的併發訪問
synchronized同步方法
- 方法內的變數為執行緒安全,而例項變數非執行緒安全。
- 不同執行緒呼叫同一物件裡的synchronized方法時,是同步的(排隊進行)。也就是必須等執行緒執行完
synchronized
方法時,下一執行緒才能執行synchronized
方法。 - 可重入鎖: 一個執行緒得到物件鎖後,再次請求此物件鎖時是可以得到該物件的鎖的。子類也可以呼叫父類的同步方法。
- 出現異常,鎖自動釋放
- 子類方法不會繼承
synchronized
關鍵字,需要手動在子類方法中加上。
synchronized同步語句塊
- 多個執行緒處理同一個物件的
synchronized(this)
同步語句塊時,只能排隊執行 - 同一個物件的
synchronized(this)
和synchronized
同步方法之間也是同步的。即同一時間只有一個執行緒可執行synchronized程式碼塊或方法中的程式碼 synchronized(非this物件x)
,是將x物件作為“物件監視器”- 當多個執行緒同時執行
synchronized(x){}
同步程式碼塊時呈同步效果 - 當其他執行緒執行x物件中
synchronizd
同步方法時呈同步效果 - 當其他執行緒執行x物件方法裡的
synchronized(this)
程式碼塊時呈同步效果
- 當多個執行緒同時執行
- 靜態同步
synchronized
方法與synchronized(class)
程式碼塊是對Class類進行持鎖。 - 當執行緒在等帶根本不可能被釋放的鎖是,就會出現死鎖。
- 如果同時持有相同的鎖物件,執行緒之間就是同步的。注意物件的屬性改變,執行結果還是同步的。
volatile關鍵字
volatile
: 強制的從公共記憶體進行取值,而不是從執行緒私有資料棧中取得變數的值。可以使變數在多個執行緒間可見,但缺點是不支援原子性。
synchronized
和volatile
比較:
- 關鍵字volatile是執行緒同步的輕量級實現,所以volatile效能比synchronized好,並且volatile只能修飾變數,而synchronized可修飾方法和程式碼塊。
- 多執行緒訪問volatile不會發生阻塞,而synchronized會出現阻塞
- volatile能保證資料可見性,不保證原子性;synchronized可以保證原子性,也可以間接保證可見性,因為synchronized會將私有記憶體和公共記憶體中的資料做同步。
- volatile解決的是變數在多個執行緒間的可見性,synchronized解決的是多個執行緒訪問資源的同步性(互斥加可見)。
原子類:
如AtomicBoolean
,AtomicInteger
,AtomicLong
等。一個原子型別就是一個原子操作可用的型別,可在沒有鎖的情況下做到執行緒安全。但原子類的方法間的呼叫卻不是原子的,需要用同步。