標籤: javahtml
[TOC]java
本文對多線程基礎知識進行梳理,主要包括多線程的基本使用,對象及變量的併發訪問,線程間通訊,lock的使用,定時器,單例模式,以及線程狀態與線程組。git
花了一週時間閱讀《java多線程編程核心技術》(高洪巖 著),本文算是此書的整理概括,書中幾乎全部示例,我都親手敲了一遍,並上傳到了個人github上,有興趣的朋友能夠到個人github下載。源碼採用maven構建,多線程這部分源碼位於java-multithread
模塊中。github
- 倉庫地址:java-learning
- git clone:
git@github.com:brianway/java-learning.git
基礎知識編程
isAlive()
測試線程是否處於活動狀態sleep()
讓「正在執行的線程」休眠getId()
取得線程惟一標識yield()
放棄當前的CPU資源stop()
,suspend()
,resume()
等,已經棄用了,由於可能產生數據不一樣步等問題。比較和辨析api
currentThread()
方法返回值肯定。例如,直接在main方法裏調用run方法,和調用線程的start方法,打印出的當前線程結果是不一樣的。interrupted()
和isInterrupted()
interrupted()
是類的靜態方法,測試當前線程是否已是中斷狀態,執行後具備將狀態標誌清除爲false的功能。isInterrupted()
是類的實例方法,測試Thread對象是否已是中斷狀態,但不清楚狀態標誌。sleep()
和wait()
區別:
java.lang.IllegalMonitorStateException
異常方法 | 是否釋放鎖 | 備註 |
---|---|---|
wait | 是 | wait和notify/notifyAll是成對出現的, 必須在synchronize塊中被調用 |
sleep | 否 | 可以使低優先級的線程得到執行機會 |
yield | 否 | yield方法使當前線程讓出CPU佔有權, 但讓出的時間是不可設定的 |
synchronized
關鍵字
synchronized(x){}
同步代碼塊時呈同步效果線程的私有堆棧圖安全
讀取公共內存圖多線程
辨析和零散補充併發
變量在內存中的工做過程圖oracle
wait()
和notify()
/notifyAll()
。wait使線程中止運行,notify使中止的線程繼續運行。
wait()
:將當前執行代碼的線程進行等待,置入"預執行隊列"。
wait(long)
是等待某一時間內是否有線程對鎖進行喚醒,超時則自動喚醒。notify()
:通知可能等待該對象的對象鎖的其餘線程。隨機挑選一個呈wait狀態的線程,使它等待獲取該對象的對象鎖。
notifyAll()
和notify()
差很少,只不過是使全部正在等待隊中等待同一共享資源的「所有」線程從等待狀態退出,進入可運行狀態。PipedInputStream
和PipedOutputStream
PipedReader
和PipedWriter
join()
:等待線程對象銷燬,具備使線程排隊運行的做用。
join(long)
可設定等待的時間join
與synchronized
的區別:join在內部使用wait()方法進行等待;synchronized使用的是「對象監視器」原理做爲同步join(long)
與sleep(long)
的區別:join(long)內部使用wait(long)實現,因此join(long)具備釋放鎖的特色;Thread.sleep(long)不釋放鎖。ThreadLocal
類:每一個線程綁定本身的值
initialValue()
方法可使變量初始化,從而解決get()返回null的問題InheritableThreadLocal
類可在子線程中取得父線程繼承下來的值。ReentrantLock
類:實現線程之間的同步互斥,比synchronized更靈活
lock()
,調用了的線程就持有了「對象監視器」,效果和synchronized同樣Condition
實現等待/通知:比wait()和notify()/notyfyAll()更靈活,好比可實現多路通知。
Object與Condition方法對比
Object | Condition |
---|---|
wait() | await() |
wait(long timeout) | await(long time,TimeUnit unit) |
notify() | signal() |
notifyAll() | signalAll() |
一些API
方法 | 說明 |
---|---|
int getHoldCount() |
查詢當前線程保持此鎖定的個數,即調用lock()方法的次數 |
int getQueueLength() |
返回正在等待獲取此鎖定的線程估計數 |
int getWaitQueueLength(Condition condition) |
返回等待與此鎖定相關的給定條件Conditon的線程估計數 |
boolean hasQueueThread(Thread thread) |
查詢指定的線程是否正在等待獲取此鎖定 |
boolean hasQueueThreads() |
查詢是否有線程正在等待獲取此鎖定 |
boolean hasWaiters(Condition) |
查詢是否有線程正在等待與此鎖定有關的condition條件 |
boolean isFair() |
判斷是否是公平鎖 |
boolean isHeldByCurrentThread() |
查詢當前線程是否保持此鎖定 |
boolean isLocked() |
查詢此鎖定是否由任意線程保持 |
void lockInterruptibly() |
若是當前線程未被中斷,則獲取鎖定,若是已經被中斷則出現異常 |
boolean tryLock() |
僅在調用時鎖定未被另外一個線程保持的狀況下,才獲取該鎖定 |
boolean tryLock(long timeout,TimeUnit unit) |
若是鎖定在給定等待時間內沒有被另外一個線程保持,且當前線程未被中斷,則獲取該鎖定 |
ReentrantReadWriteLock
類
經常使用API
方法 | 說明 |
---|---|
schedule(TimerTask task, Date time) | 在指定的日期執行某一次任務 |
scheduleAtFixedRate(TimerTask task, Date firstTime, long period) | 在指定的日期以後按指定的間隔週期,無限循環的執行某一任務 |
schedule(TimerTask task, long delay) | 以執行此方法的當前時間爲基準時間,在此時間基礎上延遲指定的毫秒數後執行一次TimerTask任務 |
schedule(TimerTask task, long delay, long period) | 以執行此方法的當前時間爲基準時間,在此時間基礎上延遲指定的毫秒數,再以某一間隔時間無限次數地執行某一TimerTask任務 |
schedule
和scheduleAtFixedRate
的區別:schedule不具備追趕執行性;scheduleAtFixedRate具備追趕執行性方法與狀態關係示意圖
Thread.State
枚舉類,參閱官網APIEnum Thread.StateSimpleDateFormat
非線程安全,解決辦法有:
setUncaughtExceptionHandler()
給指定線程對線設置異常處理器setDefaultUncaughtExceptionHandler()
對全部線程對象設置異常處理器