線程池ThreadPoolExecutor
JDK5帶來(lái)的一大改進(jìn)就是Java的并發(fā)能力塘辅,它提供了三種并發(fā)武器:并發(fā)框架Executor月幌,并發(fā)集合類型如ConcurrentHashMap,并發(fā)控制類如CountDownLatch等野崇;圣經(jīng)《Effective Java》也說(shuō),盡量使用Exector而不是直接用Thread類進(jìn)行并發(fā)編程。
AsyncTask內(nèi)部也使用了線程池處理并發(fā)冒晰;線程池通過(guò)ThreadPoolExector
類構(gòu)造,這個(gè)構(gòu)造函數(shù)參數(shù)比較多竟块,它允許開(kāi)發(fā)者對(duì)線程池進(jìn)行定制壶运,我們先看看這每個(gè)參數(shù)是什么意思,然后看看Android是以何種方式定制的浪秘。
ThreadPoolExecutor的其他構(gòu)造函數(shù)最終都會(huì)調(diào)用如下的構(gòu)造函數(shù)完成對(duì)象創(chuàng)建工作:
1234567
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
corePoolSize: 核心線程數(shù)目蒋情,即使線程池沒(méi)有任務(wù)埠况,核心線程也不會(huì)終止(除非設(shè)置了allowCoreThreadTimeOut參數(shù))可以理解為“常駐線程”
maximumPoolSize: 線程池中允許的最大線程數(shù)目;一般來(lái)說(shuō)棵癣,線程越多辕翰,線程調(diào)度開(kāi)銷越大;因此一般都有這個(gè)限制狈谊。
keepAliveTime: 當(dāng)線程池中的線程數(shù)目比核心線程多的時(shí)候喜命,如果超過(guò)這個(gè)keepAliveTime的時(shí)間,多余的線程會(huì)被回收河劝;這些與核心線程相對(duì)的線程通常被稱為緩存線程
unit: keepAliveTime的時(shí)間單位
workQueue: 任務(wù)執(zhí)行前保存任務(wù)的隊(duì)列壁榕;這個(gè)隊(duì)列僅保存由execute提交的Runnable任務(wù)
threadFactory: 用來(lái)構(gòu)造線程池的工廠;一般都是使用默認(rèn)的赎瞎;
handler: 當(dāng)線程池由于線程數(shù)目和隊(duì)列限制而導(dǎo)致后續(xù)任務(wù)阻塞的時(shí)候牌里,線程池的處理方式。
那么务甥,當(dāng)一個(gè)新的任務(wù)到達(dá)的時(shí)候牡辽,線程池中的線程是如何調(diào)度的呢?(別慌敞临,講這么一大段線程池的知識(shí)态辛,是為了理解AsyncTask;Be Patient)
如果線程池中線程的數(shù)目少于corePoolSize挺尿,就算線程池中有其他的沒(méi)事做的核心線程因妙,線程池還是會(huì)重新創(chuàng)建一個(gè)核心線程;直到核心線程數(shù)目到達(dá)corePoolSize(常駐線程就位)
如果線程池中線程的數(shù)目大于或者等于corePoolSize票髓,但是工作隊(duì)列workQueue沒(méi)有滿,那么新的任務(wù)會(huì)放在隊(duì)列workQueue中铣耘,按照FIFO的原則依次等待執(zhí)行洽沟;(當(dāng)有核心線程處理完任務(wù)空閑出來(lái)后,會(huì)檢查這個(gè)工作隊(duì)列然后取出任務(wù)默默執(zhí)行去)
如果線程池中線程數(shù)目大于等于corePoolSize蜗细,并且工作隊(duì)列workQueue滿了裆操,但是總線程數(shù)目小于maximumPoolSize,那么直接創(chuàng)建一個(gè)線程處理被添加的任務(wù)炉媒。
如果工作隊(duì)列滿了踪区,并且線程池中線程的數(shù)目到達(dá)了最大數(shù)目maximumPoolSize,那么就會(huì)用最后一個(gè)構(gòu)造參數(shù)handler
處理吊骤;**默認(rèn)的處理方式是直接丟掉任務(wù)缎岗,然后拋出一個(gè)異常。
總結(jié)起來(lái)白粉,也即是說(shuō)传泊,當(dāng)有新的任務(wù)要處理時(shí)鼠渺,先看線程池中的線程數(shù)量是否大于 corePoolSize,再看緩沖隊(duì)列 workQueue 是否滿眷细,最后看線程池中的線程數(shù)量是否大于 maximumPoolSize拦盹。另外,當(dāng)線程池中的線程數(shù)量大于 corePoolSize 時(shí)溪椎,如果里面有線程的空閑時(shí)間超過(guò)了 keepAliveTime普舆,就將其移除線程池,這樣校读,可以動(dòng)態(tài)地調(diào)整線程池中線程的數(shù)量沼侣。
我們以API 22為例,看一看AsyncTask里面的線程池是以什么參數(shù)構(gòu)造的地熄;AsyncTask里面有“兩個(gè)”線程池华临;一個(gè)THREAD_POOL_EXECUTOR
一個(gè)SERIAL_EXECUTOR
;之所以打引號(hào)端考,是因?yàn)槠鋵?shí)SERIAL_EXECUTOR
也使用THREAD_POOL_EXECUTOR
實(shí)現(xiàn)的雅潭,只不過(guò)加了一個(gè)隊(duì)列弄成了串行而已,那么這個(gè)THREAD_POOL_EXECUTOR
是如何構(gòu)造的呢却特?
123456789
private static final int CORE_POOL_SIZE = CPU_COUNT + 1;private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;private static final int KEEP_ALIVE = 1;private static final BlockingQueue<Runnable> sPoolWorkQueue = new LinkedBlockingQueue<Runnable>(128); public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
可以看到扶供,AsyncTask里面線程池是一個(gè)核心線程數(shù)為CPU + 1
,最大線程數(shù)為CPU * 2 + 1
裂明,工作隊(duì)列長(zhǎng)度為128的線程池椿浓;并且沒(méi)有傳遞handler
參數(shù),那么使用的就是默認(rèn)的Handler(拒絕執(zhí)行).
那么問(wèn)題來(lái)了:
如果任務(wù)過(guò)多闽晦,那么超過(guò)了工作隊(duì)列以及線程數(shù)目的限制導(dǎo)致這個(gè)線程池發(fā)生阻塞扳碍,那么悲劇發(fā)生,默認(rèn)的處理方式會(huì)直接拋出一個(gè)異常導(dǎo)致進(jìn)程掛掉仙蛉。假設(shè)你自己寫(xiě)一個(gè)異步圖片加載的框架笋敞,然后用AsyncTask實(shí)現(xiàn)的話,當(dāng)你快速滑動(dòng)ListView的時(shí)候很容易發(fā)生這種異常荠瘪;這也是為什么各大ImageLoader都是自己寫(xiě)線程池和Handlder的原因夯巷。
這個(gè)線程池是一個(gè)靜態(tài)變量;那么在同一個(gè)進(jìn)程之內(nèi)哀墓,所有地方使用到的AsyncTask默認(rèn)構(gòu)造函數(shù)構(gòu)造出來(lái)的AsyncTask都使用的是同一個(gè)線程池趁餐,如果App模塊比較多并且不加控制的話,很容易滿足第一條的崩潰條件篮绰;如果你不幸在不同的AsyncTask的doInBackgroud里面訪問(wèn)了共享資源后雷,那么就會(huì)發(fā)生各種并發(fā)編程問(wèn)題。
在AsyncTask全部執(zhí)行完畢之后,進(jìn)程中還是會(huì)常駐corePoolSize個(gè)線程喷面;在Android 4.4 (API 19)以下星瘾,這個(gè)corePoolSize是hardcode的,數(shù)值是5惧辈;API 19改成了cpu + 1
琳状;也就是說(shuō),在Android 4.4以前盒齿;如果你執(zhí)行了超過(guò)五個(gè)AsyncTask念逞;然后啥也不干了,進(jìn)程中還是會(huì)有5個(gè)AsyncTask線程边翁;不信翎承,你看:
Handler
AsyncTask里面的handler很簡(jiǎn)單,如下(API 22代碼):
12345
private static final InternalHandler sHandler = new InternalHandler();public InternalHandler() { super(Looper.getMainLooper());}
注意符匾,這里直接用的主線程的Looper叨咖;如果去看API 22以下的代碼,會(huì)發(fā)現(xiàn)它沒(méi)有這個(gè)構(gòu)造函數(shù)啊胶,而是使用默認(rèn)的甸各;默認(rèn)情況下,Handler會(huì)使用當(dāng)前線程的Looper焰坪,如果你的AsyncTask是在子線程創(chuàng)建的趣倾,那么很不幸,你的onPreExecute
和onPostExecute
并非在UI線程執(zhí)行某饰,而是被Handler post到創(chuàng)建它的那個(gè)線程執(zhí)行儒恋;如果你在這兩個(gè)線程更新了UI,那么直接導(dǎo)致崩潰黔漂。這也是大家口口相傳的AsyncTask必須在主線程創(chuàng)建的原因诫尽。
另外,AsyncTask里面的這個(gè)Handler是一個(gè)靜態(tài)變量炬守,也就是說(shuō)它是在類加載的時(shí)候創(chuàng)建的箱锐;如果在你的APP進(jìn)程里面,以前從來(lái)沒(méi)有使用過(guò)AsyncTask劳较,然后在子線程使用AsyncTask的相關(guān)變量,那么導(dǎo)致靜態(tài)Handler初始化浩聋,如果在API 16以下观蜗,那么會(huì)出現(xiàn)上面同樣的問(wèn)題;這就是AsyncTask必須在主線程初始化 的原因衣洁。
事實(shí)上墓捻,在Android 4.1(API 16)以后,在APP主線程ActivityThread的main函數(shù)里面,直接調(diào)用了AscynTask.init
函數(shù)確保這個(gè)類是在主線程初始化的砖第;另外撤卢,init這個(gè)函數(shù)里面獲取了InternalHandler
的Looper,由于是在主線程執(zhí)行的梧兼,因此放吩,AsyncTask的Handler用的也是主線程的Looper。這個(gè)問(wèn)題從而得到徹底的解決羽杰。
AsyncTask是并行執(zhí)行的嗎渡紫?
現(xiàn)在知道AsyncTask內(nèi)部有一個(gè)線程池,那么派發(fā)給AsyncTask的任務(wù)是并行執(zhí)行的嗎考赛?
答案是不確定惕澎。在Android 1.5剛引入的時(shí)候,AsyncTask的execute
是串行執(zhí)行的颜骤;到了Android 1.6直到Android 2.3.2唧喉,又被修改為并行執(zhí)行了,這個(gè)執(zhí)行任務(wù)的線程池就是THREAD_POOL_EXECUTOR
忍抽,因此在一個(gè)進(jìn)程內(nèi)八孝,所有的AsyncTask都是并行執(zhí)行的;但是在Android 3.0以后梯找,如果你使用execute
函數(shù)直接執(zhí)行AsyncTask唆阿,那么這些任務(wù)是串行執(zhí)行的;(你說(shuō)蛋疼不)源代碼如下:
123
public final AsyncTask<Params, Progress, Result> execute(Params... params) { return executeOnExecutor(sDefaultExecutor, params);}
這個(gè)sDefaultExecutor
就是用來(lái)執(zhí)行任務(wù)的線程池锈锤,那么它的值是什么呢驯鳖?繼續(xù)看代碼:
1
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
因此結(jié)論就來(lái)了:Android 3.0以上,AsyncTask默認(rèn)并不是并行執(zhí)行的久免;
為什么默認(rèn)不并行執(zhí)行浅辙?
也許你不理解,為什么AsyncTask默認(rèn)把它設(shè)計(jì)為串行執(zhí)行的呢阎姥?
由于一個(gè)進(jìn)程內(nèi)所有的AsyncTask都是使用的同一個(gè)線程池執(zhí)行任務(wù)记舆;如果同時(shí)有幾個(gè)AsyncTask一起并行執(zhí)行的話,恰好AysncTask的使用者在doInbackgroud
里面訪問(wèn)了相同的資源呼巴,但是自己沒(méi)有處理同步問(wèn)題泽腮;那么就有可能導(dǎo)致災(zāi)難性的后果!
由于開(kāi)發(fā)者通常不會(huì)意識(shí)到需要對(duì)他們創(chuàng)建的所有的AsyncTask對(duì)象里面的doInbackgroud
做同步處理衣赶,因此诊赊,API的設(shè)計(jì)者為了避免這種無(wú)意中訪問(wèn)并發(fā)資源的問(wèn)題,干脆把這個(gè)API設(shè)置為默認(rèn)所有串行執(zhí)行的了府瞄。如果你明確知道自己需要并行處理任務(wù)碧磅,那么你需要使用executeOnExecutor(Executor exec,Params... params)
這個(gè)函數(shù)來(lái)指定你用來(lái)執(zhí)行任務(wù)的線程池,同時(shí)為自己的行為負(fù)責(zé)。(處理同步問(wèn)題)
實(shí)際上《Effective Java》里面有一條原則說(shuō)的就是這種情況:不要在同步塊里面調(diào)用不可信的外來(lái)函數(shù)鲸郊。這里明顯違背了這個(gè)原則:AsyncTask這個(gè)類并不知道使用者會(huì)在doInBackgroud
這個(gè)函數(shù)里面做什么丰榴,但是對(duì)它的行為做了某種假設(shè)。
如何讓AsyncTask并行執(zhí)行秆撮?
正如上面所說(shuō)四濒,如果你確定自己做好了同步處理,或者你沒(méi)有在不同的AsyncTask里面訪問(wèn)共享資源像吻,需要AsyncTask能夠并行處理任務(wù)的話峻黍,你可以用帶有兩個(gè)參數(shù)的executeOnExecutor
執(zhí)行任務(wù):
1234567
new AsyncTask<Void, Void, Vo @Override protected Void doInBackground(Void... params) { // do something return null; }}.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
更好的AsyncTask
從上面的分析得知,AsyncTask有如下問(wèn)題:
默認(rèn)的AsyncTask如果處理的任務(wù)過(guò)多拨匆,會(huì)導(dǎo)致程序直接崩潰姆涩;
AsyncTask類必須在主線程初始化,必須在主線程創(chuàng)建惭每,不然在API 16以下很大概率崩潰骨饿。
如果你曾經(jīng)使用過(guò)AsyncTask,以后不用了台腥;在Android 4.4以下宏赘,進(jìn)程內(nèi)也默認(rèn)有5個(gè)AsyncTask線程;在Android 4.4以上黎侈,默認(rèn)有CPU + 1
個(gè)線程察署。
Android 3.0以上的AsyncTask默認(rèn)是串行執(zhí)行任務(wù)的;如果要并行執(zhí)行需要調(diào)用低版本沒(méi)有的API峻汉,處理麻煩贴汪。
因此我們對(duì)系統(tǒng)的AsyncTask做了一些修改,在不同Android版本提供一致的行為休吠,并且提高了使用此類的安全性扳埂,主要改動(dòng)如下:
添加對(duì)于任務(wù)過(guò)多導(dǎo)致崩潰的異常保護(hù);在這里進(jìn)行必要的數(shù)據(jù)統(tǒng)計(jì)上報(bào)工作瘤礁;如果出現(xiàn)這個(gè)問(wèn)題阳懂,說(shuō)明AsyncTask不適合這種場(chǎng)景了,需要考慮重構(gòu)柜思;
移植API 22對(duì)于Handler的處理岩调;這樣就算在線程創(chuàng)建異步任務(wù),也不會(huì)有任何問(wèn)題赡盘;
提供串行執(zhí)行和并行執(zhí)行的execute
方法誊辉;默認(rèn)串行執(zhí)行,如果明確知道自己在干什么亡脑,可以使用executeParallel
并行執(zhí)行。
在doInbackgroud
里面頻繁崩潰的地方加上try..catch
;自己處理數(shù)據(jù)上報(bào)工作霉咨。
完整代碼見(jiàn)gist蛙紫,BetterAsyncTask
原文地址:http://weishu.me/2016/01/18/dive-into-asynctask/
大體流程
? excute()方法中首先直接調(diào)用preExcute()方法
? AsyncTask的構(gòu)造方法構(gòu)造了mWorkder這個(gè)WorkerRunnable對(duì)象.再用mWorker構(gòu)造一個(gè)FutureTask對(duì)象丟到線程池里面去執(zhí)行
? AsyncTask的成員變量有個(gè)InternalHandler,構(gòu)造的時(shí)候進(jìn)行初始化.
? FutureTask轉(zhuǎn)調(diào)mWorker的run方法最后在線程池的子線程調(diào)用doInBackGround()方法.
? 然后FutureTask調(diào)用setResult()方法把運(yùn)行結(jié)果返回,完成后調(diào)用FutureTask的done方法.這里面用InternalHandler發(fā)了個(gè)消息給主線程,最后拿到結(jié)果調(diào)用 finish()
- FutureTask類
它需要Callable接口類型的參數(shù),在AsyncTask類中途戒,創(chuàng)建了WorkerRunnable的實(shí)現(xiàn)類和FutureTask類坑傅,在run方法中調(diào)用
private static abstract class WorkerRunnable<Params, Result>
implements Callable<Result> {
Params[] mParams;
}
public AsyncTask() {
mWorker = new WorkerRunnable<Params, Result>() {
public Result call() throws Exception {
//調(diào)用熟悉的doInBackground方法,在子線程中執(zhí)行喷斋,
return postResult(doInBackground(mParams));
}
};
mFuture = new FutureTask<Result>(mWorker) {
@Override
protected void done() {
try {
postResultIfNotInvoked(get());
} catch (InterruptedException e) {
android.util.Log.w(LOG_TAG, e);
} catch (ExecutionException e) {
throw new RuntimeException("An error occured
while executing doInBackground()",
e.getCause());
} catch (CancellationException e) {
postResultIfNotInvoked(null);
}
}
};
}
//執(zhí)行execute方法時(shí)
public final AsyncTask<Params, Progress, Result> execute(Params... params) {
onPreExecute();
mWorker.mParams = params;
//將任務(wù)添加到Executor的實(shí)現(xiàn)類ThreadPoolExecutor里面
exec.execute(mFuture);
}
//FutureTask任務(wù)
public class FutureTask<V> implements RunnableFuture<V>{
private volatile int state;//任務(wù)運(yùn)行的狀態(tài)
//構(gòu)造函數(shù)java.util.concurrent.Callable
public FutureTask(Callable<V> callable) {
}
//取消任務(wù)通過(guò)線程執(zhí)行interrupt
public boolean cancel(boolean mayInterruptIfRunning) {
try {
Thread t = runner;
if (t != null)
t.interrupt();
} finally { // final state
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
}
}
//此方法調(diào)用awaitDone唁毒,它會(huì)阻塞線程,一直等到線程執(zhí)行完成
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
//變量c就是構(gòu)造函數(shù)傳的Callable<V> callable對(duì)象
public void run() {
if (c != null && state == NEW) {
V result;
result = c.call();
//call里面的任務(wù)執(zhí)行完畢之后星爪,在set方法里面調(diào)用finishCompletion方法浆西,
之后調(diào)用done方法表示任務(wù)執(zhí)行完成。
set(result);
}
}
//消除和信號(hào)顽腾,所有等待的線程近零,調(diào)用done()
private void finishCompletion() {
// assert state > COMPLETING;
for (WaitNode q; (q = waiters) != null;) {
if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
for (;;) {
Thread t = q.thread;
if (t != null) {
q.thread = null;
LockSupport.unpark(t);
}
WaitNode next = q.next;
if (next == null)
break;
q.next = null; // unlink to help gc
q = next;
}
break;
}
}
done();
callable = null; // to reduce footprint
}
//異步任務(wù)執(zhí)行完成拔妥,回調(diào)
protected void done() {
}
}
ThreadPoolExecutor
任務(wù)執(zhí)行在這個(gè)類里面用到了ReentrantLock鎖顾孽,實(shí)現(xiàn)了ExecutorService接口。
//addWorker方法第二個(gè)參數(shù)core含義:true表示核心線程5蝴猪,false表示非核心線程128
public void execute(Runnable command) {
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
else if (!addWorker(command, false))
//調(diào)用handler.rejectedExecution拋出異常
reject(command);
}
private boolean addWorker(Runnable firstTask, boolean core) {
for (;;) {
int c = ctl.get();
int rs = runStateOf(c);
for (;;) {
int wc = workerCountOf(c);//當(dāng)前work線程數(shù)量
if (wc >= CAPACITY ||
wc >= (core ? corePoolSize : maximumPoolSize))
return false;
if (compareAndIncrementWorkerCount(c))
break retry;
c = ctl.get(); // Re-read ctl
if (runStateOf(c) != rs)
continue retry;
}
}
Worker w = new Worker(firstTask);
Thread t = w.thread;
final ReentrantLock mainLock = this.mainLock;
mainLock.lock();
try {
workers.add(w);
} finally {
mainLock.unlock();
}
t.start();
return true;
}
InternalHandler
任務(wù)執(zhí)行完時(shí)在子線程漓摩,此時(shí)會(huì)發(fā)送一個(gè)handler消息裙士,handler接收到這個(gè)消息就會(huì)調(diào)用AsyncTask的finish方法,接著調(diào)用onPostExecute管毙。
private void finish(Result result) {
if (isCancelled()) {
onCancelled(result);
} else {
onPostExecute(result);
}
mStatus = Status.FINISHED;
}
private static class InternalHandler extends Handler {
public void handleMessage(Message msg) {
AsyncTaskResult result = (AsyncTaskResult) msg.obj;
switch (msg.what) {
case MESSAGE_POST_RESULT:
result.mTask.finish(result.mData[0]);
break;
case MESSAGE_POST_PROGRESS:
result.mTask.onProgressUpdate(result.mData);
break;
}
}
}
異步任務(wù)執(zhí)行的結(jié)果腿椎,主線程無(wú)法輕易的獲取
Java FutureTask 異步任務(wù)操作提供了便利性
1.獲取異步任務(wù)的返回值
2.監(jiān)聽(tīng)異步任務(wù)的執(zhí)行完畢
3.取消異步任務(wù)
doBackground(call)
call的返回值在Future的done方法中獲取
->onPostExecute
new MyTask().execute();
實(shí)例化:
new AsyncTask() -> new FutureTask()
執(zhí)行:
Executor.execute(mFuture) -> SerialExecutor.myTasks(隊(duì)列)
-> (線程池)THREAD_POOL_EXECUTOR.execute
線程池中的所有線程,為了執(zhí)行異步任務(wù)
CORE_POOL_SIZE 核心線程數(shù)
MAXIMUM_POOL_SIZE 最大線程數(shù)量
KEEP_ALIVE 1s閑置回收
TimeUnit.SECONDS 時(shí)間單位
sPoolWorkQueue 異步任務(wù)隊(duì)列
sThreadFactory 線程工廠
如果當(dāng)前線程池中的數(shù)量小于corePoolSize锅风,創(chuàng)建并添加的任務(wù)酥诽。
如果當(dāng)前線程池中的數(shù)量等于corePoolSize,緩沖隊(duì)列 workQueue未滿皱埠,那么任務(wù)被放入緩沖隊(duì)列肮帐、等待任務(wù)調(diào)度執(zhí)行。
如果當(dāng)前線程池中的數(shù)量大于corePoolSize边器,緩沖隊(duì)列workQueue已滿训枢,并且線程池中的數(shù)量小于maximumPoolSize,新提交任務(wù)會(huì)創(chuàng)建新線程執(zhí)行任務(wù)忘巧。
如果當(dāng)前線程池中的數(shù)量大于corePoolSize恒界,緩沖隊(duì)列workQueue已滿,并且線程池中的數(shù)量等于maximumPoolSize砚嘴,新提交任務(wù)由Handler處理十酣。
當(dāng)線程池中的線程大于corePoolSize時(shí)涩拙,多余線程空閑時(shí)間超過(guò)keepAliveTime時(shí),會(huì)關(guān)閉這部分線程耸采。
public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);
1.線程池容量不夠拋出異常
2.內(nèi)存泄露
3.一個(gè)線程兴泥,一個(gè)異步任務(wù)(?)
測(cè)試代碼
public class FutureTest1 {
public static void main(String[] args) {
System.out.println("main ID: " + Thread.currentThread().getId());
Task work = new Task();
FutureTask<Integer> future = new FutureTask<Integer>(work) {
// 異步任務(wù)執(zhí)行完成虾宇,回調(diào)
@Override
protected void done() {
try {
System.out.println("done:" + get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
};
// 線程池(使用了預(yù)定義的配置)
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(future);
try {
Thread.sleep(1000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
// 取消異步任務(wù)
// future.cancel(true);
try {
// 阻塞搓彻,等待異步任務(wù)執(zhí)行完畢
System.out.println(future.get()); // 獲取異步任務(wù)的返回值
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
// 異步任務(wù)
static class Task implements Callable<Integer> {
// 返回異步任務(wù)的執(zhí)行結(jié)果
@Override
public Integer call() throws Exception {
int i = 0;
for (; i < 10; i++) {
try {
System.out.println(Thread.currentThread().getName() + "_"
+ i);
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("ID: " + Thread.currentThread().getId());
return i;
}
}
}