基本知識
一 線程優(yōu)先級
二 線程的狀態(tài)
三 線程函數(shù)
四 線程間通信
參考:java并發(fā)編程的藝術
一 線程優(yōu)先級
- 線程優(yōu)先級決定線程可以多分或少分配一些處理器資源,時間片的數(shù)量兰伤;
- 針對頻繁阻塞(休眠或IO)的線程需要設置較高優(yōu)先級内颗,占用CPU時間短。
針對偏重計算(較多CPU時間或偏運算)設置較低優(yōu)先級敦腔,確保不會獨占均澳。 - Java默認優(yōu)先級為5,范圍1-10符衔。
線程優(yōu)先級不能作為程序正確性的依賴找前,因為OS可以完全不理會Java的優(yōu)先級設置。
二 線程的狀態(tài)
-
狀態(tài)說明
- 初始狀態(tài)
NEW
:A thread that has not yet started is in this state. - 運行狀態(tài)
RUNNABLE
:A thread executing in the Java virtual machine is in this state.(就緒+運行) - 阻塞狀態(tài)
BLOCKED
thread that is blocked waiting for a monitor lock is in this state. (synchronized塊/方法) - 等待狀態(tài)
WAITING
:A thread that is waiting indefinitely for another thread to perform a particular action is in this state.(其他線程通知notify判族、notifyAll或中斷) - 超時等待狀態(tài)
TIMED_WAITING
:A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state. (指定時間內(nèi)可以返回的等待狀態(tài)) - 終止狀態(tài)
TERMINATED
:A thread that has exited is in this state.
- 初始狀態(tài)
-
狀態(tài)轉(zhuǎn)換圖
阻塞狀態(tài)是線程阻塞在進入synchronized關鍵字修飾的方法塊或代碼塊時的狀態(tài)躺盛,
但是阻塞在concurrent包中l(wèi)ock接口的線程狀態(tài)是等待狀態(tài),因為concurrent包中l(wèi)ock接口對于阻塞的實現(xiàn)均使用了LockSupport類中的相關方法五嫂。
三 線程函數(shù)
-
Daemon線程 后臺線程
Thread daemon = new Thread(new DaemonRunner()); daemon.setDaemon(true);//啟動之前設置 daemon.start();
如果java虛擬機中不存在非Daemon線程時颗品,java虛擬機將會推出。
JVM退出時沃缘,所有的Daemon線程都會被立即停止躯枢。finally塊代碼并不會執(zhí)行; -
主線程結束和子線程結束之間的關系 鏈接
情況1:正常情況下槐臀,主線程啟動了子線程锄蹂,主線程、子線程各自執(zhí)行水慨,彼此不受影響得糜。
情況2:需求是主線程執(zhí)行結束,由主線程啟動的子線程都結束
情況3:需求是子線程執(zhí)行結束晰洒,主線程等待啟動的子線程都結束之后再結束
-
中斷標記 鏈接
一個線程不應該由其他線程來強制中斷或停止朝抖,而是應該由線程自己自行停止。
Thread.stop(不保證資源的正確釋放), Thread.suspend(暫停時不釋放鎖), Thread.resume 都被廢棄了谍珊。中斷可以理解為線程的一個標志位治宣,表示該線程是否被求他線程進行了中斷操作。
相當于其它線程打了個中斷招呼砌滞,具體自己中斷還是繼續(xù)運行侮邀,由自己來決定。具體來說贝润,當對一個線程绊茧,調(diào)用
interrupt()
時,
① 如果線程處于等待狀態(tài)(例如處于sleep, wait, join)那么線程將立即退出被等待狀態(tài)打掘,并拋出一個InterruptedException異常,僅此而已华畏。被鎖時不響應;
② 如果線程處于正撑羟铮活動狀態(tài),那么會將該線程的中斷標志設置為 true亡笑,僅此而已拼岳。被設置中斷標志的線程將繼續(xù)正常運行,不受影響况芒。interrupt() 并不能真正的中斷線程,需要被調(diào)用的線程自己進行配合才行叶撒。
也就是說绝骚,一個線程如果有被中斷的需求,那么就可以這樣做祠够。
① 在正常運行任務時压汪,經(jīng)常檢查本線程的中斷標志位isInterrupted()
,如果被設置了中斷標志就自行停止線程古瓤。
② 在調(diào)用等待方法時正確處理InterruptedException異常止剖。(例如,catch異常后就結束線程落君。)Thread.interrupted()會清除標志位穿香,并不是代表線程又恢復了,可以理解為僅僅是代表它已經(jīng)響應完了這個中斷信號然后又重新置為可以再次接收信號的狀態(tài)绎速。
InterruptedException拋出時皮获,也會清楚中斷標記位。
Thread.sleep() : 睡眠不釋放鎖
Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.
四 線程間通信
-
共享變量
共享變量在共享內(nèi)存中纹冤,但是每個線程可以有一份拷貝洒宝,加速程序執(zhí)行,所以線程看到的變量不一定是新的萌京。- 關鍵字
volatile
:訪問必須從共享內(nèi)存獲取雁歌,修改必須同步刷新回共享內(nèi)存,保證內(nèi)存可見性知残。 - 關鍵字
synchronized
:同步塊或方法靠瞎,線程的訪問是同步互斥的。
- 關鍵字
-
等待/通知機制
wait()
:釋放對象的鎖橡庞,變?yōu)閃aiting狀態(tài)较坛;wait返回的前提是notify線程釋放鎖,自己拿到對象的鎖扒最;
wait(long)
:返回也需要鎖丑勤;
notify()
:通知一個等待線程由等待隊列進入同步隊列,Waiting變Blocking吧趣;
notifyAll()
:通知所有等待的線程法竞;
等待通知機制依賴于同步機制耙厚,目的就是確保等待線程返回時可以感知到通知線程對變量所做的修改。1.等待方 synchronized (obj) { while (condition does not hold) obj.wait(); ... // Perform action appropriate to condition } 2.通知方 synchronized (obj) { 改變條件 obj.notify(); }
thread.join()
:等待線程結束岔霸,內(nèi)部使用wait-notifypublic final synchronized void join(long millis) throws InterruptedException { long base = System.currentTimeMillis(); long now = 0; if (millis < 0) { throw new IllegalArgumentException("timeout value is negative"); } if (millis == 0) { while (isAlive()) { wait(0); } } else { while (isAlive()) { long delay = millis - now; if (delay <= 0) { break; } wait(delay); now = System.currentTimeMillis() - base; } } }
-
管道輸入輸出流
管道IO與文件IO或網(wǎng)絡IO不同薛躬,主要用于線程之間的數(shù)據(jù)傳輸,傳輸?shù)拿浇闉?strong>內(nèi)存呆细;
面向字節(jié):PipedInputStream型宝、PipedOutputStream
面向字符流:PipedReader,PipedWriterPipedReader in = new PipedReader(); PipedWriter out = new PipedWriter(); out.connect(in);//輸入流和輸出流需要連接絮爷,否則異常
@夢工廠2018.3.21