序言
近日后臺(tái)需要一些數(shù)據(jù)囚戚,需要從網(wǎng)上爬取酵熙,但是爬取的過(guò)程中,由于訪問(wèn)速度太頻繁驰坊,造成IP被封匾二,最終通過(guò)線程池解決;想要借此機(jī)會(huì),總結(jié)一下線程池的有關(guān)知識(shí)
線程池框架
- 從圖中可以看出察藐,
Executor
提供了整個(gè)線程池的基本實(shí)現(xiàn)皮璧,而Executors
則提供了各線程池方法的基本工廠方法;下面我們將從線程池的基本運(yùn)用到源碼解析逐一分析
Executor
- 一個(gè)接口分飞,也是線程池框架的基礎(chǔ)悴务;方法只有一個(gè)
execute()
,可以用于自定義繼承實(shí)現(xiàn)任務(wù)的執(zhí)行方式;直接已知子類有:ExecutorService
,ScheduledExecutorService
- 去耦合譬猫,可以將任務(wù)(
Runnable
實(shí)現(xiàn))與執(zhí)行分離 - 不嚴(yán)格要求異步惨寿,可以立即執(zhí)行,看自己怎么實(shí)現(xiàn)删窒;如文檔
demo
:
class DirectExecutor implements Executor {
public void execute(Runnable r) {
r.run(); //此時(shí)該任務(wù)是在調(diào)用的線程中執(zhí)行的裂垦,并非異步
}
}
- 更多的還是要求異步執(zhí)行
class ThreadPerTaskExecutor implements Executor {
public void execute(Runnable r) {
new Thread(r).start(); //新開辟條線程執(zhí)行任務(wù)
}
}
ExecutorService
- 一個(gè)接口,繼承了
Executor
肌索,但是與Executor
不同的是蕉拢,它還提供了終止的方法:shutdown()
可以使對(duì)象拒絕再接受新的任務(wù),但是以前提交的任務(wù)還是會(huì)繼續(xù)執(zhí)行诚亚;shutdownNow()
不僅可以使對(duì)象拒絕接受新的任務(wù)晕换,還嘗試阻止以前已經(jīng)提交的任務(wù)開始執(zhí)行,同時(shí)該方法還會(huì)試圖中斷當(dāng)前正在執(zhí)行的任務(wù) - 一個(gè)不再使用的
ExecutorService
應(yīng)該被關(guān)閉站宗,從而釋放它所占有的資源 -
submit()
方法擴(kuò)展了原始的Executor
的execute(Runnable)
方法,可以返回一個(gè)Future
對(duì)象闸准,該Future
對(duì)象代表了該等待執(zhí)行的任務(wù),可以通過(guò)該對(duì)象來(lái)取消執(zhí)行或者判斷是否成功執(zhí)行(Future
的get()
方法可以判斷)
ScheduledExecutorService
繼承自
ExecutorService
的一個(gè)接口梢灭,實(shí)現(xiàn)類為ScheduledThreadPoolExecutor
可以使任務(wù)定期執(zhí)行或者延遲一段時(shí)間之后執(zhí)行
schedule()
方法可以創(chuàng)建各種延時(shí)的任務(wù)夷家,同時(shí)返回一個(gè)代表該任務(wù)的對(duì)象()ScheduledFuture
用于檢測(cè)任務(wù)執(zhí)行情況和取消執(zhí)行scheduleWithFixedDelay()
方法可以創(chuàng)建和執(zhí)行任務(wù),該任務(wù)具有定時(shí)性當(dāng)任務(wù)通過(guò)
Executor.execute(Runnable)
或者ExecutorService
的submit()
方法提交時(shí)敏释,默認(rèn)的延時(shí)是0库快;零延時(shí)和負(fù)延時(shí)都被當(dāng)做立即執(zhí)行對(duì)待-
所有的定時(shí)方法都支持相對(duì)延時(shí)或者時(shí)間段作為參數(shù),而不是絕對(duì)時(shí)間或者日期钥顽,示例:
schedule(task, date.getTime() - System.currentTimeMillis(), TimeUnit.MILLISECONDS)
-
官方示例代碼:即創(chuàng)建一個(gè)任務(wù)每10s執(zhí)行一次义屏,執(zhí)行1h后取消
import static java.util.concurrent.TimeUnit.*; class BeeperControl { private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); public void beepForAnHour() { Runnable beeper = () -> System.out.println("beep"); ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS); Runnable canceller = () -> beeperHandle.cancel(true); scheduler.schedule(canceller, 1, HOURS); } }
Future
- 一個(gè)泛型接口,用于表示一個(gè)異步執(zhí)行的結(jié)果蜂大,可以通過(guò)該對(duì)象來(lái)判斷異步是否執(zhí)行完成(
isDone()
)闽铐;同時(shí)也可以通過(guò)該對(duì)象來(lái)取回異步執(zhí)行的返回結(jié)果(只能通過(guò)get()
方法取回,需要判斷異步是否完成奶浦,get()
方法將會(huì)阻塞直到任務(wù)完成)兄墅;也可以通過(guò)cancel()
方法來(lái)取消該任務(wù)的執(zhí)行
Callable<V>
- 泛型接口,
V
表示最終異步執(zhí)行結(jié)果的返回類型 - 與
Runnable
的區(qū)別是:Callable
可以返回結(jié)果财喳,同時(shí)Callable
還可以拋出一個(gè)可檢查的異常(當(dāng)無(wú)法正常返回結(jié)果時(shí))察迟,但是Runnable
不行
Executors
- 直接繼承自
Object
斩狱,擁有許多工廠方法以支持Executor
,ExecutorService
,ScheduledExecutorService
,ThreadFactory
,和Callable
對(duì)象
對(duì) ExecutorService 的支持
newCachedThreadPool()
- 使用
newCachedThreadPool()
的靜態(tài)方法返回一個(gè)新創(chuàng)建的線程池對(duì)象;此方法會(huì)創(chuàng)建一個(gè)線程池扎瓶,同時(shí)該線程池中的線程會(huì)被重用(如果空閑可用的話)所踊,如果沒(méi)有可用的線程,會(huì)新建一個(gè)線程并添加到該線程池中;該方法適用于需要執(zhí)行許多耗時(shí)短暫的任務(wù)集(使線程得到最大程度上的復(fù)用概荷,提高程序性能) - 注意該線程池中的線程如果在
60s
內(nèi)沒(méi)有被重用的話秕岛,將被回收,同時(shí)移除出該線程池误证;所以不用擔(dān)心因?yàn)榫€程池空閑而造成對(duì)系統(tǒng)資源的消耗 - 實(shí)際上是返回一個(gè)
ThreadPoolExecutor
對(duì)象继薛,而ThreadPoolExecutor
繼承于ExecutorService
(源代碼見下);實(shí)際使用的構(gòu)造函數(shù)是public ThreadPoolExecutor?(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue)
愈捅,表示的是創(chuàng)建一個(gè)無(wú)界線程池(即線程池中線程數(shù)量沒(méi)有固定)遏考;注意設(shè)置的60L
對(duì)應(yīng)的是long keepAliveTime
參數(shù),表示的是如果線程池中空閑線程數(shù)量大于corePoolSize
的話蓝谨,在keepAliveTime
時(shí)間內(nèi)沒(méi)有該線程沒(méi)有重用灌具,那么會(huì)自動(dòng)回收該線程,同時(shí)這里將corePoolSize
設(shè)置為0譬巫,那么在任務(wù)執(zhí)行完成之后所有線程將會(huì)自動(dòng)回收咖楣;至于BlockingQueue<Runnable> workQueue)
參數(shù),只是一個(gè)用于維持由execute()
方法提交的任務(wù)隊(duì)列
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
- 示例代碼如下芦昔;下列代碼的輸出如下诱贿;根據(jù)輸出可以看出,其實(shí)線程池中并沒(méi)有創(chuàng)建10條線程咕缎,正真的最大活躍線程數(shù)量只有7條珠十,同時(shí)也并不是按照我們預(yù)期的那樣,任務(wù)的執(zhí)行是分配到特定線程的锨阿,而是當(dāng)
thread-1
執(zhí)行完其本身的任務(wù)后宵睦,線程池中有空閑線程(thread-1
),所以此時(shí)并沒(méi)有使用其他線程去執(zhí)行任務(wù)墅诡,而是復(fù)用了thread-1
。
//示例輸出
index...0--Thread info Thread[pool-1-thread-1,5,main]--Thread activeCount 4
index...2--Thread info Thread[pool-1-thread-1,5,main]--Thread activeCount 5
index...1--Thread info Thread[pool-1-thread-2,5,main]--Thread activeCount 5
index...5--Thread info Thread[pool-1-thread-1,5,main]--Thread activeCount 6
index...4--Thread info Thread[pool-1-thread-2,5,main]--Thread activeCount 6
index...8--Thread info Thread[pool-1-thread-1,5,main]--Thread activeCount 7
index...6--Thread info Thread[pool-1-thread-4,5,main]--Thread activeCount 7
index...9--Thread info Thread[pool-1-thread-5,5,main]--Thread activeCount 7
index...3--Thread info Thread[pool-1-thread-3,5,main]--Thread activeCount 7
index...7--Thread info Thread[pool-1-thread-2,5,main]--Thread activeCount 7
//示例代碼桐智,同時(shí)注意調(diào)用`shutdownNow()`方法后
public class demo {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService service =Executors.newCachedThreadPool();
for(int i=0;i<10;i++){
service.execute(new CallDemo(i));
}
}
}
public class CallDemo implements Runnable {
private final int index;
public CallDemo(int index) {
this.index = index;
}
@Override
public void run() {
System.out.println("index..."+index+
"--Thread info "+ Thread.currentThread()+"--Thread activeCount "+Thread.activeCount());
}
}
(如上代碼)另外還需要注意的是末早,當(dāng)所有任務(wù)都執(zhí)行完了以后,線程池并不是馬上停止的说庭,而是此時(shí)所有的線程處于空閑狀態(tài)然磷,會(huì)如上所說(shuō)的等待60s之后再自動(dòng)回收停止(如果想要任務(wù)執(zhí)行完成之后馬上停止,可以調(diào)用
shutdownNow()
或者shutdown()
方法)-
另外說(shuō)一下
Thread[pool-1-thread-1,5,main]
代表的意思(由Thread.currentThread()
輸出刊驴,實(shí)際上currentThread()
方法返回的是一個(gè)Thread
對(duì)象姿搜,只不過(guò)在println()
函數(shù)中會(huì)默認(rèn)調(diào)用toString()
方法寡润,所以應(yīng)該看Thread
的toString()
方法,如下)舅柜,對(duì)應(yīng)下面的代碼應(yīng)該可以很清楚各位置輸出代表的意思了public String toString() { ThreadGroup group = getThreadGroup(); if (group != null) { return "Thread[" + getName() + "," + getPriority() + "," + group.getName() + "]"; } else { return "Thread[" + getName() + "," + getPriority() + "," + "" + "]"; } }
-
至于在代碼中使用
service.execute(new CallDemo(i));
與使用service.submit(new CallDemo(i));
的區(qū)別梭纹,需要注意的是ThreadPoolExecutor
類并沒(méi)有重寫submit()
方法,所以應(yīng)該在其父類AbstractExecutorService
中找致份,如下:
可見变抽,其實(shí)submit()
中也是調(diào)用了execute()
方法,只是還可以通過(guò)Future
來(lái)取得返回值或者檢測(cè)任務(wù)執(zhí)行情況(具體見上Future
說(shuō)明)public Future<?> submit(Runnable task) { if (task == null) throw new NullPointerException(); //null這里可以看出當(dāng)沒(méi)有返回值時(shí)會(huì)默認(rèn)返回null RunnableFuture<Void> ftask = newTaskFor(task, null); execute(ftask); return ftask; } public <T> Future<T> submit(Runnable task, T result) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task, result); execute(ftask); return ftask; } public <T> Future<T> submit(Callable<T> task) { if (task == null) throw new NullPointerException(); RunnableFuture<T> ftask = newTaskFor(task); execute(ftask); return ftask; }
newCachedThreadPool(ThreadFactory threadFactory)
-
參數(shù)
ThreadFactory
對(duì)象用于創(chuàng)建新線程氮块;該方法可以根據(jù)需要?jiǎng)?chuàng)建線程绍载,所謂的根據(jù)需要是指可以通過(guò)ThreadFactory
創(chuàng)建所需要的線程;至于ThreadFactory
可以使程序能夠使用其他的線程子類和屬性等滔蝉,而不僅局限與new Thread()
击儡,示例:class SimpleThreadFactory implements ThreadFactory { public Thread newThread(Runnable r) { //在這里也可以對(duì)該線程做一些共同的初始化工作 return new Thread(r); } }
該線程池中的線程也會(huì)被復(fù)用
適用于對(duì)線程有特殊初始條件需求或者特殊屬性需求時(shí)
newFixedThreadPool?(int nThreads)
會(huì)創(chuàng)建一個(gè)具有
nThread
條的線程池,如果待處理事件多余nThread
蝠引,同時(shí)工作的線程任然只有nThread
條曙痘,剩余的事件將會(huì)等待線程空閑如果線程池中的線程因?yàn)槭录惓6K止,同時(shí)還有待處理事件立肘,那么會(huì)重新創(chuàng)建一條線程(也就是說(shuō)保持線程池中的線程數(shù)量為
nThread
)該線程池中線程需要明確的調(diào)用
shutdown()
來(lái)終止還有一個(gè)
newFixedThreadPool?(int nThreads, ThreadFactory threadFactory)
边坤,其中ThreadFactory
的使用同newCachedThreadPool
-
這個(gè)返回的任然是一個(gè)
ThreadPoolExecutor
對(duì)象,調(diào)用構(gòu)造函數(shù)為ThreadPoolExecutor?(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)
谅年,這里將corePoolSize
設(shè)置為了傳入的線程數(shù)量茧痒,keepAliveTime
參數(shù)相當(dāng)于沒(méi)有起到限定作用(需要注意的是keepAliveTime
參數(shù)只有在線程池中線程數(shù)量大于corePoolSize
的時(shí)候才會(huì)起限定作用,但是這里不存在線程數(shù)量超過(guò)corePoolSize
的情況融蹂,所以相當(dāng)于沒(méi)有用)旺订,所以使用該方法的時(shí)候需要我們顯示的調(diào)用shutdown()
和shutdownNow()
方法來(lái)回收系統(tǒng)資源(但是需要注意的是如果調(diào)用shutdownNow()
方法的話,有可能會(huì)導(dǎo)致任務(wù)沒(méi)有執(zhí)行完超燃,因?yàn)?code>shutdownNow()會(huì)試圖終止正在執(zhí)行的線程区拳,但是shutdown()
是會(huì)等待當(dāng)前任務(wù)完成的)public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
newSingleThreadExecutor?()
線程池中只有一條線程,如果該線程因?yàn)槭录惓6K止意乓,而事件隊(duì)列中還有待處理事件樱调,那么會(huì)重新創(chuàng)建一條線程
可以保證事件順序按照提交順序執(zhí)行
同樣可以根據(jù)需要,使用
newSingleThreadExecutor?(ThreadFactory threadFactory)
來(lái)創(chuàng)建特定的線程-
至于其與
newFixedThreadPool(1)
的區(qū)別届良,參見下面代碼ExecutorService executors = Executors.newFixedThreadPool(1); System.out.println(((ThreadPoolExecutor) executors).getCorePoolSize());//1 ThreadPoolExecutor executor = (ThreadPoolExecutor) executors; executor.setCorePoolSize(4); System.out.println(executor.getCorePoolSize() + "..." + ((ThreadPoolExecutor) executors).getCorePoolSize());//4...4 executors.shutdownNow();
通過(guò)上面代碼笆凌,可見,newFixedThreadPool(1)
線程池中線程的數(shù)量是可以調(diào)整的士葫,但是對(duì)于newSingleThreadExecutor?()
線程池中線程的數(shù)量是不可調(diào)整的乞而,如下:
ExecutorService single = Executors.newSingleThreadExecutor();
ThreadPoolExecutor singles = (ThreadPoolExecutor) single;
singles.setCorePoolSize(4);
System.out.println(((ThreadPoolExecutor) single).getCorePoolSize());
這樣將會(huì)報(bào)類型轉(zhuǎn)換錯(cuò)誤:
java.util.concurrent.Executors$FinalizableDelegatedExecutorService cannot be cast to java.util.concurrent.ThreadPoolExecutor
-
實(shí)際上該函數(shù)返回的是一個(gè)
FinalizableDelegatedExecutorService
對(duì)象,源碼見下慢显;其中FinalizableDelegatedExecutorService
是Executors
類中的一個(gè)靜態(tài)包裝類爪模,使用了默認(rèn)訪問(wèn)權(quán)限欠啤,只能同包中類才能訪問(wèn)public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
-
這里雖然使用了構(gòu)造函數(shù)
ThreadPoolExecutor?(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue)
,但是實(shí)際上是不需要顯示調(diào)用shutdown()
來(lái)顯示回收系統(tǒng)資源的屋灌,因?yàn)樵诎b類FinalizableDelegatedExecutorService
中洁段,重寫了Object
類的finalize()
方法,在其中已經(jīng)調(diào)用了shutdown()
声滥,而finalize()
方法是在垃圾回收時(shí)系統(tǒng)自動(dòng)調(diào)用的眉撵。其實(shí)現(xiàn)如下(但是經(jīng)過(guò)實(shí)驗(yàn),垃圾回收這種情況是不定的(可能涉及到垃圾回收的相關(guān)知識(shí))落塑,所以筆者建議還是在不需要時(shí)顯示調(diào)用shutdown()
要好一些)static class FinalizableDelegatedExecutorService extends DelegatedExecutorService { FinalizableDelegatedExecutorService(ExecutorService executor) { super(executor); } protected void finalize() { super.shutdown(); //這里已經(jīng)自動(dòng)調(diào)用了shutdown纽疟,在垃圾回收的時(shí) 候會(huì)自動(dòng)釋放系統(tǒng)資源 } }
newWorkStealingPool?() 與 newWorkStealingPool(int)
核心為
work-stealing
,意為工作竊取
,意為當(dāng)一個(gè)線程完成自己的任務(wù)后憾赁,去其他的線程隊(duì)列中竊取任務(wù)執(zhí)行(即將一個(gè)大任務(wù)分解為數(shù)個(gè)小任務(wù)污朽,為了減小線程執(zhí)行任務(wù)時(shí)造成的競(jìng)爭(zhēng)(同步鎖等),將這些小任務(wù)放在不同的雙端隊(duì)列中龙考,當(dāng)一個(gè)線程執(zhí)行完任務(wù)后去其他隊(duì)列末端(這也是設(shè)計(jì)成雙端隊(duì)列的原因)取任務(wù)來(lái)執(zhí)行)蟆肆,任務(wù)結(jié)果放在另一個(gè)獨(dú)立隊(duì)列中。使用線程池作為執(zhí)行任務(wù)線程的管理者晦款,來(lái)實(shí)現(xiàn)
fork/join
模式的任務(wù)執(zhí)行策略炎功,所謂[圖片上傳失敗...(image-d9e8ea-1517904101171)],就是一種利用一臺(tái)計(jì)算機(jī)上的多個(gè)處理器進(jìn)行同類型問(wèn)題并行計(jì)算的模式缓溅,通過(guò)對(duì)大規(guī)模問(wèn)題逐步分解蛇损,直到可以作為獨(dú)立的小任務(wù)在單獨(dú)的線程中執(zhí)行,結(jié)合線程間的通信機(jī)制實(shí)現(xiàn)相當(dāng)于遞歸迭代的并行版本坛怪,這和現(xiàn)在流行的Map/Reduce
模式有些類似淤齐,只不過(guò)Map/Reduce
是在多臺(tái)計(jì)算機(jī)上執(zhí)行的。---[圖片上傳失敗...(image-52f120-1517904101172)]-
可通過(guò)
Runtime
類的availableProcessors
方法得到虛擬機(jī)的可用處理器數(shù)量Runtime run = Runtime.getRuntime(); System.out.println(run.availableProcessors());
無(wú)法保證執(zhí)行順序
unconfigurableExecutorService(ExecutorService executor)
- 主要用于包裝線程池袜匿,包裝后的線程池不能被修改(屬性等)更啄,相當(dāng)于
final
,實(shí)際上最終代碼里面是將傳入的executor
賦值給了一個(gè)private final ExecutorService e
成員變量,從而保證線程池屬性等不可變
對(duì) ThreadFactory 的支持
-
ThreadFactory
顧名思義是一個(gè)用于創(chuàng)建線程的線程工廠方法居灯,可以根據(jù)需要?jiǎng)?chuàng)建線程
defaultThreadFactory()
- 使用默認(rèn)線程工廠創(chuàng)建線程祭务,這些線程都屬于同一線程組,并且都是非守護(hù)線程
對(duì) ScheduledExecutorService 的支持
newScheduledThreadPool?(int corePoolSize)和
newScheduledThreadPool?(int corePoolSize,ThreadFactory threadFactory)
創(chuàng)建指定數(shù)量線程的線程池穆壕,能夠延時(shí)或者定期執(zhí)行任務(wù)
-
本質(zhì)上該方法返回的是一個(gè)
ScheduledThreadPoolExecutor
對(duì)象待牵,而ScheduledThreadPoolExecutor
對(duì)象調(diào)用的又是其父類ThreadPoolExecutor
的構(gòu)造方法(如下),通過(guò)其傳入的參數(shù)可知喇勋,實(shí)際上我們最終得到的是一個(gè)具有corePoolSize
大小的ThreadPoolExecutor
線程池//構(gòu)造函數(shù) public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
-
這里
ScheduledThreadPoolExecutor
在ThreadPoolExecutor
的增加了定時(shí)執(zhí)行任務(wù)的功能,即核心scheduleWithFixedDelay()
,scheduleAtFixedRate()
方法偎行,同樣可以通過(guò)其返回的ScheduledFuture
對(duì)象來(lái)對(duì)任務(wù)進(jìn)行判斷是否完成和嘗試取消任務(wù),簡(jiǎn)單使用如下(CallDemo
為自定義實(shí)現(xiàn)了Runnable
的類):ScheduledExecutorService service = Executors.newScheduledThreadPool(5); service.scheduleWithFixedDelay(new CallDemo(1),5000l,1000l,TimeUnit.MILLISECONDS); service.scheduleAtFixedRate(new CallDemo(2),5000l,1000l,TimeUnit.MILLISECONDS);
需要注意的時(shí)該任務(wù)會(huì)一直執(zhí)行下去川背,除非發(fā)生一下情況:1. 明確的通過(guò)其返回值
ScheduledFuture
來(lái)取消或者終止贰拿;2. 執(zhí)行的任務(wù)產(chǎn)生異常;其中對(duì)于第二種情況熄云,使用ScheduledFuture
的isDone()
會(huì)得到true
膨更,而且使用get()
會(huì)跑出ExecutionException
異常至于
scheduleWithFixedDelay()
和scheduleAtFixedRate()
的區(qū)別,前者的延時(shí)是對(duì)前一段任務(wù)結(jié)束開始計(jì)算缴允,后者的延時(shí)是前一段任務(wù)開始就開始計(jì)算了荚守,特別時(shí)當(dāng)任務(wù)比較耗時(shí),超過(guò)了設(shè)定的延時(shí)時(shí)练般,前者任然會(huì)保持該延時(shí)執(zhí)行矗漾,但是后者會(huì)等待前一段任務(wù)完成之后立即執(zhí)行,但是不會(huì)同時(shí)執(zhí)行
newSingleThreadScheduledExecutor?() 和
newSingleThreadScheduledExecutor?(ThreadFactory threadFactory)
- 創(chuàng)建一個(gè)單一線程的線程池延時(shí)或者定期執(zhí)行任務(wù)
- 同樣當(dāng)該線程因?yàn)槭录惓6K止時(shí)薄料,在
shutdown()
之前會(huì)再創(chuàng)建一個(gè)線程來(lái)代替 - 與
newScheduledThreadPool(1)
的區(qū)別同樣也是通過(guò)newSingleThreadScheduledExecutor?()
創(chuàng)建出來(lái)的線程池不允許增加新線程和其他屬性
unconfigurableScheduledExecutorService?(ScheduledExecutorService executor)
- 同樣用于包裝線程池敞贡,相當(dāng)與
final
對(duì) Callable 的支持
Callable<Object> callable?(Runnable task)
- 執(zhí)行任務(wù),同時(shí)返回
null
<T> Callable<T> callable?(Runnable task,T result)
- 執(zhí)行指定返回結(jié)果
result
摄职,這在需要調(diào)用Callable
但是結(jié)果無(wú)返回值時(shí)的會(huì)很有用