java多線程
[TOC]
創(chuàng)建線程
class MyRunnable implements Runnable{
public void run(){
//線程執(zhí)行代碼
}
}
Runnable r = new MyRunnable();
//創(chuàng)建線程并啟動(dòng)
Thread t = new Thread(r);
t.start();
直接調(diào)用Thread類或Runnable類的run方法并不會(huì) 創(chuàng)建線程馏锡,只會(huì)在本線程內(nèi)執(zhí)行
中斷線程
- 當(dāng)線程的run方法執(zhí)行完畢后或者出現(xiàn)了沒(méi)有捕獲的異常時(shí),線程將終止为严。
- 當(dāng)對(duì)一個(gè)線程調(diào)用interrupt方法時(shí)痢畜,線程中的中斷標(biāo)志將被置位垛膝,這是每個(gè)線程都有的boolean標(biāo)志,每個(gè)線程都應(yīng)不時(shí)檢查這個(gè)標(biāo)志丁稀,已判斷線程是否中斷吼拥。
- 使用Thread.currentThread()方法獲取當(dāng)前線程,Thread.currentThread().isInterrupted方法返回當(dāng)前線程被置位的狀態(tài)线衫。但是當(dāng)線程被阻塞(sleep或wait)時(shí)將無(wú)法檢測(cè)中斷狀態(tài)凿可,當(dāng)對(duì)阻塞狀態(tài)的線程調(diào)用interrupt方法時(shí)線程會(huì)拋出interrupted Exception異常。
- interrupted測(cè)試當(dāng)前線程是否中斷授账,執(zhí)行方法會(huì)將線程的中斷狀態(tài)置為false枯跑。
線程狀態(tài)
- New(新創(chuàng)建)
- Runnable(可運(yùn)行)
- Blocked(被阻塞)
- Waiting(等待)
- Timed Waiting(計(jì)時(shí)等待)
- Terminated(被終止)
-
新創(chuàng)建線程
使用new操作剛剛創(chuàng)建的線程,此時(shí)線程還未開(kāi)始運(yùn)行白热。****
-
可運(yùn)行線程
一旦調(diào)用了Thread的start方法線程就處于runable狀態(tài)敛助,一個(gè)可運(yùn)行的線程可能正在運(yùn)行也可能沒(méi)有運(yùn)行,取決于操作系統(tǒng)的上下文切換屋确。一旦一個(gè)線程開(kāi)始運(yùn)行纳击,可能隨時(shí)被中斷续扔,目的是為了讓其他線程獲得運(yùn)行機(jī)會(huì),操作系統(tǒng)搶占式調(diào)度系統(tǒng)給每一個(gè)可運(yùn)行線程一個(gè)時(shí)間片來(lái)執(zhí)行任務(wù)焕数,時(shí)間片用完時(shí)纱昧,系統(tǒng)剝奪線程的運(yùn)行權(quán),并給其他線程運(yùn)行機(jī)會(huì)堡赔。
-
被阻塞或等待的線程
當(dāng)線程處于被阻塞或等待狀態(tài)時(shí)砌些,它暫時(shí)不活動(dòng),不運(yùn)行任何代碼切消耗資源加匈,直到線程調(diào)度器重新激活它。
- 當(dāng)一個(gè)線程試圖獲取一個(gè)內(nèi)部對(duì)象鎖仑荐,而該鎖被其他線程持有雕拼,則該線程進(jìn)入阻塞狀態(tài)。當(dāng)其他線程釋放鎖粘招,并且調(diào)度去允許本線程持有時(shí)啥寇,該線程恢復(fù)為非阻塞狀態(tài)。
- 當(dāng)線程等待另一個(gè)線程通知調(diào)度器一個(gè)條件時(shí)洒扎,它自己進(jìn)入等待狀態(tài)辑甜。
- Thread.sleep、Object.wait袍冷、Thread.join磷醋、Lock.tryLock、Condition.await方法將線程進(jìn)入等待狀態(tài)胡诗。
當(dāng)一個(gè)線程被阻塞或等待時(shí)邓线,另一個(gè)線程被調(diào)度為可運(yùn)行狀態(tài),當(dāng)一個(gè)線程重新被激活時(shí)煌恢,調(diào)度器檢查是否比當(dāng)前運(yùn)行線程具有更高優(yōu)先級(jí)骇陈,如果優(yōu)先級(jí)更高則從當(dāng)前運(yùn)行線程中選一個(gè)剝奪當(dāng)前線程優(yōu)先級(jí),選擇一個(gè)新的線程運(yùn)行。
-
線程有倆種原因被終止:
- run方法正常退出而自然死亡瑰抵。
- 因?yàn)闆](méi)有捕獲的異常終止運(yùn)行而意外死亡你雌。
線程屬性
線程優(yōu)先級(jí)
- 每一個(gè)線程有一個(gè)優(yōu)先級(jí),默認(rèn)情況二汛,一個(gè)線程繼承它的父線程的優(yōu)先級(jí)婿崭,可以用setPriority方法提高或降低任何一個(gè)線程的優(yōu)先級(jí)∠捌叮可以將優(yōu)先級(jí)設(shè)置為在MIN_PRIORITY(1) 至MAX_PRIORITY(10)之間逛球,NORM_PRIORITY=5。
- 線程優(yōu)先級(jí)高度依賴于操作系統(tǒng)調(diào)度苫昌,java優(yōu)先級(jí)被映射到操作系統(tǒng)的優(yōu)先級(jí)颤绕。優(yōu)先個(gè)數(shù)也許更多幸海,也許更少。在linux上線程優(yōu)先級(jí)被忽略奥务,所有線程具有相同優(yōu)先級(jí)物独。
守護(hù)線程
可以通過(guò)調(diào)用t.setDaemon(true);將線程轉(zhuǎn)換為守護(hù)線程。守護(hù)線程的唯一用途就是為其他線程提供服務(wù)氯葬。當(dāng)只剩下守護(hù)線城時(shí)虛擬機(jī)就退出了挡篓,因?yàn)闆](méi)必要繼續(xù)運(yùn)行程序了。
未捕獲異常處理器
- 線程的run方法不能拋出任何被檢測(cè)的異常帚称,不被檢測(cè)的異常將導(dǎo)致線程終止官研。但是不需要任何catch子句來(lái)處理可以被傳播的異常,相反在線程死亡前異常被傳遞到一個(gè)用于未捕獲異常的處理器闯睹。該處理器必須屬于一個(gè)實(shí)現(xiàn)Thread.UncaughtExceptionHandler接口的類戏羽。這個(gè)接口只有一個(gè)方法:
void uncaughtException(Thread t,Throwable e)
可以用setUncaughtExceptionHandler方法為任何線程安裝一個(gè)處理器。也可以用Thread類的靜態(tài)方法setDefaultUncaughtExceptionHandler為所有線程安裝一個(gè)默認(rèn)處理器楼吃,替換處理器可以使用日志API發(fā)送未捕獲異常的報(bào)告到日志文件始花。
-
默認(rèn)處理器為空,但是如果不為獨(dú)立的線程安裝處理器孩锡,此時(shí)的處理器就是該線程的ThreadGroup對(duì)象酷宵。
線程組(ThreadGroup)是一個(gè)可以統(tǒng)一管理的線程集合。默認(rèn)情況所有線程屬于相同的線程組躬窜,但是也可以建立其他的組浇垦,現(xiàn)在引入了更好的特性用于線程集合的操作,不建議在自己的程序中使用線程組斩披。
-
ThreadGroup類實(shí)現(xiàn)了Thread.UncaughtExceptionHandler接口溜族,它的uncaughtException方法做如下操作:
- 如果該線程組有父線程組,那么父線程組的uncaughtException方法被調(diào)用垦沉。
- 否則如果Thread.getDefaultExceptionHandler方法返回一個(gè)非空的處理器煌抒,則調(diào)用該處理器。
- 否則如果Throwable是ThreadDeath的一個(gè)實(shí)例厕倍,什么都不做寡壮。
- 否則,線程的名字以及Throwable的棧蹤跡被輸出讹弯。
同步
鎖對(duì)象
如果使用鎖就不能使用帶資源的try語(yǔ)句况既。
- 有兩種機(jī)制防止代碼塊受并發(fā)訪問(wèn)的干擾,java提供一個(gè)synchronized關(guān)鍵字達(dá)到這個(gè)目的组民,jdk1.5引入了ReentrantLock類棒仍,用于顯式鎖定。
//ReentrantLock顯式鎖定
myLock.lock();
try{
}finally{
myLock.unlock();
}
- 當(dāng)一個(gè)對(duì)象有自己的ReentrantLock對(duì)象時(shí)臭胜,如果倆個(gè)線程試圖訪問(wèn)同一個(gè)對(duì)象莫其,那么將觸發(fā)鎖機(jī)制癞尚,如果倆個(gè)線程訪問(wèn)倆個(gè)不同的對(duì)象則都不會(huì)發(fā)生阻塞。
可重入鎖
- synchronized和ReentrantLock都是可重入鎖乱陡,比如一個(gè)方法是synchronized浇揩,遞歸調(diào)用自己,第一個(gè)獲得鎖后第二次依然可以獲得鎖憨颠,在鎖的內(nèi)部對(duì)象有一個(gè)計(jì)數(shù)器用來(lái)跟蹤鎖的數(shù)量胳徽,unlock或synchronized方法執(zhí)行完畢后對(duì)計(jì)數(shù)器-1。
public class Widget {
public synchronized void doSomething() {
...
}
}
public class LoggingWidget extends Widget {
public synchronized void doSomething() {
System.out.println(toString() + ": calling doSomething");
super.doSomething();//若內(nèi)置鎖是不可重入的爽彤,則發(fā)生死鎖
}
}
//當(dāng)執(zhí)行子類方法時(shí)养盗,先獲取了一次Widget的鎖,在執(zhí)行super的時(shí)候适篙,又要獲取一次如果是爪瓜,如果不可重入線程就會(huì)死亡。
- 為每個(gè)鎖關(guān)聯(lián)一個(gè)獲取計(jì)數(shù)器和一個(gè)所有者線程,當(dāng)計(jì)數(shù)值為0的時(shí)候,這個(gè)所就沒(méi)有被任何線程只有.當(dāng)線程請(qǐng)求一個(gè)未被持有的鎖時(shí),JVM將記下鎖的持有者,并且將獲取計(jì)數(shù)值置為1,如果同一個(gè)線程再次獲取這個(gè)鎖,技術(shù)值將遞增,退出一次同步代碼塊,計(jì)算值遞減,當(dāng)計(jì)數(shù)值為0時(shí),這個(gè)鎖就被釋放.
條件對(duì)象
-
一個(gè)鎖對(duì)象可以有一個(gè)或多個(gè)相關(guān)的條件對(duì)象匙瘪,可以使用newCondition方法獲得一個(gè)條件對(duì)象。
例如:private Condition sufficientFunds;
-
如果條件對(duì)象發(fā)現(xiàn)條件不滿足時(shí)蝶缀,它調(diào)用await方法丹喻,當(dāng)前線程現(xiàn)在被阻塞了,并放棄了鎖翁都。等待或者鎖的線程和調(diào)用await方法的線程存在本質(zhì)上的不同碍论,一個(gè)線程調(diào)用await方式,它進(jìn)入該條件的等待集柄慰。當(dāng)鎖可用時(shí)鳍悠,該線程不能馬上解除阻塞。相反坐搔,它處于阻塞狀態(tài)藏研,直到另一個(gè)線程調(diào)用同一條件上的signalAll方法為止。
當(dāng)另一個(gè)線程轉(zhuǎn)賬時(shí)概行,它應(yīng)該調(diào)用sufficientFunds.signalAll();
這一調(diào)用重新激活因?yàn)檫@一條件而等待的所有線程蠢挡,當(dāng)這些線程從等待集中移出時(shí),它們?cè)俅纬蔀榭蛇\(yùn)行的凳忙,調(diào)度器將再次激活它們业踏。同時(shí)它們?cè)噲D重新進(jìn)入該對(duì)象,一旦鎖成為可用的涧卵,它們中的某個(gè)將從await調(diào)用返回勤家,獲得該鎖并從被阻塞的地方繼續(xù)執(zhí)行。此時(shí)應(yīng)該重新檢測(cè)條件對(duì)象柳恐,由于無(wú)法確保該條件被滿足伐脖,signalAll方法僅僅是通知正在等待的線程:此時(shí)有可能已經(jīng)滿足條件热幔,值得再去檢測(cè)該條件。
至關(guān)重要的是最終需要某個(gè)線程調(diào)用signalAll方法晓殊,當(dāng)一個(gè)線程調(diào)用await時(shí)断凶,它沒(méi)有辦法重新激活自身,只能靠其他線程來(lái)重新激活巫俺,否則將陷入死鎖狀態(tài)中认烁。
另一個(gè)方法signal則是隨機(jī)解除等待集中某個(gè)線程的阻塞狀態(tài),這比解除所有線程阻塞更加有效介汹,但是隨機(jī)選擇的線程如果發(fā)現(xiàn)仍然不能運(yùn)行却嗡,那么它再次被阻塞,如果沒(méi)有其他線程再次調(diào)用signal嘹承,系統(tǒng)就死鎖了窗价。
while(account[from] < amount){
condition.await();
}
synchronized 關(guān)鍵字
- 鎖用來(lái)保護(hù)代碼片段,任何時(shí)刻只能有一個(gè)線程執(zhí)行被保護(hù)的代碼叹卷。
- 鎖可以管理試圖進(jìn)入被保護(hù)代碼段的線程撼港。
- 鎖可以擁有一個(gè)或多個(gè)相關(guān)的條件對(duì)象
- 每個(gè)條件對(duì)象管理那些已經(jīng)進(jìn)入被保護(hù)的代碼段但還不能運(yùn)行的線程。
- java中每一個(gè)對(duì)象都有一個(gè)內(nèi)部鎖骤竹,如果一個(gè)方法用synchronized關(guān)鍵字聲明帝牡,那么對(duì)象鎖就保護(hù)整個(gè)方法。
- 內(nèi)部對(duì)象鎖只有一個(gè)相關(guān)條件蒙揣,wait方法添加一個(gè)線程到等待集中靶溜,notifyALL/notify方法解除等待線程的阻塞狀態(tài)。等價(jià)于await與signalAll懒震。
class Bank{
private double[] accounts;
public synchronized void transfer(int from,int to,int amount) throws InterruptedException{
while(accounts[from] < amount){//條件
wait();//如果條件不滿足會(huì)將當(dāng)前線程添加到等待集中
accounts[from] -= amount;
account[to] += amount;
notifyAll();//轉(zhuǎn)賬完成后通知其他等待中的線程可以檢查條件了
}
}
}
- 如果Bank類有一個(gè)靜態(tài)同步方法猜谚,那么當(dāng)該方法被調(diào)用時(shí)闹究,Bank.class對(duì)象會(huì)被鎖住,因此沒(méi)有其他線程可以調(diào)用同一個(gè)類的這個(gè)或任何其他的同步靜態(tài)方法。
內(nèi)部鎖和條件的局限性
- 不能中斷一個(gè)正在試圖獲得鎖的線程铸敏。
- 試圖獲得鎖時(shí)不能設(shè)定超時(shí)祟霍。
- 每個(gè)鎖僅有單一的條件新思,可能是不夠的姜性。
- 最好既不適用lock/Condition也不適用synchronized,許多情況下可以用java.util.concurrent包中的一種機(jī)制恐锣。
監(jiān)視器概念
- 監(jiān)視器是只包含私有域的類茅主。
- 每個(gè)監(jiān)視器類的對(duì)象有一個(gè)相關(guān)鎖。
- 使用該鎖對(duì)所有的方法進(jìn)行加鎖土榴。
- 該鎖可以有任意多個(gè)相關(guān)條件诀姚。
- java中每一個(gè)對(duì)象有一個(gè)內(nèi)部鎖和內(nèi)部的條件。
- 如果一個(gè)方法用synchronized聲明玷禽,表現(xiàn)的就像是一個(gè)監(jiān)視器方法赫段,通過(guò)調(diào)用wait/notifyAll/notify來(lái)訪問(wèn)條件變量呀打。
Volatile域
Volatile關(guān)鍵字為實(shí)例域的同步訪問(wèn)提供了一種免鎖機(jī)制。如果聲明一個(gè)域?yàn)関olatile糯笙,那么編譯器和虛擬機(jī)就知道該域是可能被另一個(gè)線程并發(fā)更新的贬丛。
volatile變量不能提供原子性,例如:public void flipDone(){ done = !done },不能確保翻轉(zhuǎn)域中的值给涕。
線程局部變量
使用ThreadLocal輔助類為各個(gè)線程提供各自的實(shí)例豺憔。
鎖測(cè)試與超時(shí)
- tryLock方法嘗試獲取鎖,成功后返回true够庙,否則返回false恭应,而且線程可以立刻離開(kāi),同時(shí)可以為tryLock設(shè)置超時(shí)參數(shù)耘眨。
- 在等待一個(gè)條件時(shí)也可以提供一個(gè)超時(shí): condition.await(100,TimeUnit.MILLISECONDS),如果一個(gè)線程被另一個(gè)線程通過(guò)調(diào)用signalAll或signal激活昼榛,或者已超時(shí),或者線程被中斷剔难,await方法將返回胆屿。
讀寫(xiě)鎖
- ReentrantLock 通用鎖,讀寫(xiě)都阻塞偶宫。
- ReentrantReadWriteLock 讀寫(xiě)鎖
private ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private Lock readLock = rwl.readLock();
private Lock writeLock = rwl.writeLock();
阻塞隊(duì)列
- 當(dāng)試圖向隊(duì)列添加元素而隊(duì)列已滿莺掠,或是香蔥隊(duì)列移出元素而隊(duì)列為空的時(shí)候,阻塞隊(duì)列導(dǎo)致線程阻塞读宙。
- 工作者線程可以周期性地將結(jié)果存儲(chǔ)在阻塞隊(duì)列中,其他工作者線程移出中間結(jié)果處理楔绞,隊(duì)列會(huì)自動(dòng)地平衡負(fù)載结闸,如果第一個(gè)線程集運(yùn)行的比第二個(gè)慢,第二個(gè)線程集在等待結(jié)果時(shí)會(huì)阻塞酒朵,如果第一個(gè)線程集運(yùn)行的快桦锄,他將等待第二個(gè)隊(duì)列集趕上來(lái)。
阻塞隊(duì)列方法
方法 | 正常動(dòng)作 | 特殊情況動(dòng)作 |
---|---|---|
add | 添加元素 | 隊(duì)列滿拋出IllegalStateException |
element | 返回頭元素 | 隊(duì)列空拋出NoSuchElementException |
offer | 添加元素返回true | 隊(duì)列滿了返回false |
peed | 返回隊(duì)列頭元素 | 隊(duì)列空返回null |
poll | 移出并返回頭元素 | 隊(duì)列空返回null |
put | 添加一個(gè)元素 | 隊(duì)列滿則阻塞 |
remove | 移出并返回頭元素 | 隊(duì)列空拋出NoSuchElementException |
take | 移出并返回頭元素 | 如果隊(duì)列空則阻塞 |
java.util.concurrent包提供了阻塞隊(duì)列的幾個(gè)變種:
- ArrayBlockingQueue(int capacity,boolean fair) 帶有容量和公平性設(shè)置的阻塞隊(duì)列蔫耽,用循環(huán)數(shù)組實(shí)現(xiàn)结耀。
- LinkedBlockingQueue 單項(xiàng)鏈表隊(duì)列
- LinkedBlockingDeque,容量沒(méi)有上邊界匙铡,但可指定最大容量图甜,并有可選參數(shù)指定是否需要公平性,若設(shè)置了公平性鳖眼,則等待時(shí)間最長(zhǎng)的線程會(huì)有限處理黑毅,公平性會(huì)降低性能。
- PriorityBlockingQueue<E>钦讳,優(yōu)先級(jí)隊(duì)列矿瘦,而不是先進(jìn)先出枕面,元素會(huì)按照優(yōu)先級(jí)順序移出,該隊(duì)列沒(méi)有容量上限缚去,但是如果隊(duì)列是空的取元素操作會(huì)阻塞潮秘,堆實(shí)現(xiàn)。
- LinkedTransferQueue類實(shí)現(xiàn)了TransferQueue接口易结,允許生產(chǎn)者線程等待枕荞,直到消費(fèi)者準(zhǔn)備就緒可以接受一個(gè)元素,如果生產(chǎn)者調(diào)用qtransfer(item); 這個(gè)調(diào)用會(huì)阻塞衬衬,直到另一個(gè)線程將元素刪除买猖。
- delayQueue 包含delayed元素?zé)o邊界有阻塞時(shí)間隊(duì)列,只有那些延遲已經(jīng)超過(guò)時(shí)間的元素可以從隊(duì)列中移出滋尉。
- blockingQueue<E> 普通阻塞隊(duì)列
- BlockingDeque<E> 雙向阻塞隊(duì)列
線程安全的集合
java.util.concurrent包提供了映射表玉控、有序集合和隊(duì)列的高效實(shí)現(xiàn):ConcurrentHashMap、ConcurrentSkipListMap狮惜、ConcurrentSkipListSet和ConcurrentLinkedQueue高诺。
與大多數(shù)集合不同,size方法不必在常量時(shí)間內(nèi)操作碾篡。確定這樣的集合當(dāng)前的大小通常需要遍歷虱而。
集合返回弱一致性的迭代器。這意味著迭代器不一定能反映出被構(gòu)造之后的所有的修改开泽,但是它們不會(huì)將一個(gè)值返回倆次牡拇。
普通集合如果在迭代器構(gòu)造之后發(fā)生改變,java.util包中的迭代器將拋出一個(gè)ConcurrentModificationException穆律。
- ConcurrentLinkedQueue<E> 線程安全無(wú)邊界非阻塞隊(duì)列惠呼。
- ConcurrentSkipListSet<E> 線程安全有序集合。
- ConcurrentHashMap
- ConcurrentSkipListMap 線程安全的hash table峦耘。具有類似redis setnx這種方法剔蹋。
Callable與Future
Runnable:沒(méi)有參數(shù)沒(méi)有返回值。
Callable:有參數(shù)有返回值辅髓,只有一個(gè)方法call泣崩。
Future:保存異步計(jì)算的結(jié)果,可以啟動(dòng)一個(gè)計(jì)算洛口,將Future對(duì)象交給某個(gè)線程矫付,然后忘掉它,F(xiàn)uture對(duì)象的持有者在結(jié)果計(jì)算好之后就可以獲得它第焰。
如果運(yùn)行該計(jì)算的線程被中斷技即,get與get帶有超時(shí)的方法都將拋出InterruptedException。
Future的方法:
方法名 | 描述 |
---|---|
V get() | 調(diào)用被阻塞直到返回結(jié)果 |
V get(long timeouot,TimeUnit unit) | 阻塞調(diào)用直到超時(shí),超時(shí)拋出InterruptedException |
boolean isDone() | 是否完成 |
boolean isCancelled() | 是否取消 |
void cancel(boolean mayInterrupt) | 取消而叼,如果還沒(méi)有開(kāi)始將不再開(kāi)始身笤。 |
FutureTask包裝器可以Callable轉(zhuǎn)換成Future和Runnable,它同時(shí)實(shí)現(xiàn)二者的接口葵陵。
執(zhí)行器
構(gòu)建一個(gè)新的線程是有一定代價(jià)的液荸,如果程序中創(chuàng)建大量臨時(shí)線程,應(yīng)該使用線程池脱篙,一個(gè)線程池包含許多準(zhǔn)備運(yùn)行的空閑線程娇钱,將Runnable對(duì)象交給線程池,就會(huì)有一個(gè)線程調(diào)用run方法绊困。當(dāng)run方法退出時(shí)文搂,線程不會(huì)死亡,二十在池中準(zhǔn)備為下一個(gè)請(qǐng)求提供服務(wù)秤朗。
執(zhí)行器類有許多靜態(tài)工廠方法用來(lái)構(gòu)建線程池
- newCachedThreadPool:必要時(shí)創(chuàng)建新線程煤蹭;空閑線程只會(huì)被保留60秒。對(duì)于每個(gè)任務(wù)取视,如果有空閑線程可用立即執(zhí)行任務(wù)硝皂,如果沒(méi)有則創(chuàng)建一個(gè)線程。
- newFixedThreadPool:該池包含固定數(shù)量的線程作谭;空閑線程會(huì)一直被保留稽物。如果任務(wù)數(shù)超過(guò)線程數(shù),將任務(wù)放到隊(duì)列中折欠。
- newSingleThreadExecutor:只有一個(gè)線程的“池”贝或,該線程順序執(zhí)行每一個(gè)提交的任務(wù)。
- newScheduledThreadPool:用于預(yù)定執(zhí)行而構(gòu)建的固定線程池锐秦,替代java.util.Timer
- newSingleThreadScheduledExecutor:用于預(yù)定執(zhí)行而構(gòu)建的單線程“池”
線程池
使用submit方法將Runnable對(duì)象或Callable對(duì)象提交給線程池咪奖。
添加任務(wù)至線程池
Future<?> submit(Runnable task),返回結(jié)果Future<?>可以調(diào)用isDone农猬、cancel、isCancelled方法售淡,但是get方法在完成的時(shí)候只是簡(jiǎn)單地返回null斤葱。
Furure<T> submit(Runnable task,T result) get方法在完成的時(shí)候返回result對(duì)象。
Future<T> submit(Callable<T> task) 返回的Future對(duì)象將在計(jì)算結(jié)果準(zhǔn)備好的時(shí)候得到它揖闸。
線程池會(huì)在方便的時(shí)候今早執(zhí)行提交的任務(wù)揍堕,submit方法會(huì)返回一個(gè)Future對(duì)象,可用來(lái)查詢?cè)撊蝿?wù)狀態(tài)汤纸。
關(guān)閉線程池
當(dāng)用完一個(gè)線程池的時(shí)候調(diào)用shutdown衩茸,該方法啟動(dòng)該池的關(guān)閉序列,被關(guān)閉的線程池不在接受新的任務(wù)贮泞,所有任務(wù)都完成后楞慈,線程池中的線程死亡幔烛。
或者調(diào)用shutdownNow,取消尚未開(kāi)始的任務(wù)囊蓝,并中斷正在運(yùn)行的線程饿悬。
獲取線程池線程數(shù)量
必須將pool對(duì)象強(qiáng)制轉(zhuǎn)換為T(mén)hreadPoolExecutor類對(duì)象,調(diào)用getLargestPoolSize方法聚霜。
預(yù)定執(zhí)行
ScheduledExecutorService接口具有為預(yù)定執(zhí)行或重復(fù)執(zhí)行任務(wù)而設(shè)計(jì)的方法狡恬,可以預(yù)定Runnablehuocallable在初始的延遲之后只運(yùn)行一次,也可以預(yù)定一個(gè)Runnable對(duì)象周期性地運(yùn)行蝎宇。
控制任務(wù)組
invokeAny方法提交所有對(duì)象到一個(gè)Callable對(duì)象的集合中弟劲,并返回某個(gè)已經(jīng)完成了的任務(wù)的結(jié)果。無(wú)法找到返回的究竟是哪個(gè)任務(wù)的結(jié)果姥芥。當(dāng)其中一個(gè)任務(wù)完成時(shí)兔乞,運(yùn)行流程就停止了。
invokeAll方法提交所有對(duì)象到一個(gè)Callable對(duì)象的集合中撇眯,并返回一個(gè)Future對(duì)象的列表报嵌,包含所有任務(wù)的返回結(jié)果。