介紹new Thread的弊端及Java四種線程池的使用,對Android同樣適用宵蕉。本文是基礎(chǔ)篇酝静,后面會分享下線程池一些高級功能。
1羡玛、new Thread的弊端
執(zhí)行一個異步任務(wù)你還只是如下new Thread嗎别智?
newThread(newRunnable(){
@Override
publicvoidrun(){
// TODO Auto-generated method stub
}
}).start();
那你就out太多了,new Thread的弊端如下:
a. 每次new Thread新建對象性能差稼稿。
b. 線程缺乏統(tǒng)一管理薄榛,可能無限制新建線程,相互之間競爭让歼,及可能占用過多系統(tǒng)資源導(dǎo)致死機(jī)或oom敞恋。
c. 缺乏更多功能,如定時執(zhí)行谋右、定期執(zhí)行硬猫、線程中斷。
相比new Thread改执,Java提供的四種線程池的好處在于:
a. 重用存在的線程啸蜜,減少對象創(chuàng)建、消亡的開銷辈挂,性能佳衬横。
b. 可有效控制最大并發(fā)線程數(shù),提高系統(tǒng)資源的使用率终蒂,同時避免過多資源競爭蜂林,避免堵塞。
c. 提供定時執(zhí)行后豫、定期執(zhí)行悉尾、單線程突那、并發(fā)數(shù)控制等功能挫酿。
2、Java 線程池
Java通過Executors提供四種線程池愕难,分別為:
newCachedThreadPool創(chuàng)建一個可緩存線程池早龟,如果線程池長度超過處理需要,可靈活回收空閑線程猫缭,若無可回收葱弟,則新建線程。
newFixedThreadPool 創(chuàng)建一個定長線程池猜丹,可控制線程最大并發(fā)數(shù)芝加,超出的線程會在隊列中等待。
newScheduledThreadPool 創(chuàng)建一個定長線程池射窒,支持定時及周期性任務(wù)執(zhí)行藏杖。
newSingleThreadExecutor 創(chuàng)建一個單線程化的線程池将塑,它只會用唯一的工作線程來執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行蝌麸。
(1). newCachedThreadPool
創(chuàng)建一個可緩存線程池点寥,如果線程池長度超過處理需要,可靈活回收空閑線程来吩,若無可回收敢辩,則新建線程。示例代碼如下:
ExecutorServicecachedThreadPool=Executors.newCachedThreadPool();
for(inti=0;i<10;i++){
finalintindex=i;
try{
Thread.sleep(index*1000);
}catch(InterruptedExceptione){
e.printStackTrace();
}
cachedThreadPool.execute(newRunnable(){
@Override
publicvoidrun(){
System.out.println(index);
}
});
}
線程池為無限大弟疆,當(dāng)執(zhí)行第二個任務(wù)時第一個任務(wù)已經(jīng)完成戚长,會復(fù)用執(zhí)行第一個任務(wù)的線程,而不用每次新建線程兽间。
(2). newFixedThreadPool
創(chuàng)建一個定長線程池历葛,可控制線程最大并發(fā)數(shù),超出的線程會在隊列中等待嘀略。示例代碼如下:
ExecutorServicefixedThreadPool=Executors.newFixedThreadPool(3);
for(inti=0;i<10;i++){
finalintindex=i;
fixedThreadPool.execute(newRunnable(){
@Override
publicvoidrun(){
try{
System.out.println(index);
Thread.sleep(2000);
}catch(InterruptedExceptione){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
因為線程池大小為3恤溶,每個任務(wù)輸出index后sleep 2秒,所以每兩秒打印3個數(shù)字帜羊。
定長線程池的大小最好根據(jù)系統(tǒng)資源進(jìn)行設(shè)置咒程。如Runtime.getRuntime().availableProcessors()∷嫌可參考PreloadDataCache帐姻。
(3) newScheduledThreadPool
創(chuàng)建一個定長線程池,支持定時及周期性任務(wù)執(zhí)行奶段。延遲執(zhí)行示例代碼如下:
ScheduledExecutorServicescheduledThreadPool=Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(newRunnable(){
@Override
publicvoidrun(){
System.out.println("delay 3 seconds");
}
},3,TimeUnit.SECONDS);
表示延遲3秒執(zhí)行饥瓷。
定期執(zhí)行示例代碼如下:
scheduledThreadPool.scheduleAtFixedRate(newRunnable(){
@Override
publicvoidrun(){
System.out.println("delay 1 seconds, and excute every 3 seconds");
}
},1,3,TimeUnit.SECONDS);
表示延遲1秒后每3秒執(zhí)行一次。
ScheduledExecutorService比Timer更安全痹籍,功能更強(qiáng)大呢铆,后面會有一篇單獨(dú)進(jìn)行對比。
(4)蹲缠、newSingleThreadExecutor
創(chuàng)建一個單線程化的線程池棺克,它只會用唯一的工作線程來執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行线定。示例代碼如下:
ExecutorServicesingleThreadExecutor=Executors.newSingleThreadExecutor();
for(inti=0;i<10;i++){
finalintindex=i;
singleThreadExecutor.execute(newRunnable(){
@Override
publicvoidrun(){
try{
System.out.println(index);
Thread.sleep(2000);
}catch(InterruptedExceptione){
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
}
結(jié)果依次輸出娜谊,相當(dāng)于順序執(zhí)行各個任務(wù)。
現(xiàn)行大多數(shù)GUI程序都是單線程的斤讥。Android中單線程可用于數(shù)據(jù)庫操作纱皆,文件操作,應(yīng)用批量安裝,應(yīng)用批量刪除等不適合并發(fā)但可能IO阻塞性及影響UI線程響應(yīng)的操作派草。