背景:每出現一個耗時操作都去創建一個新的線程必然不優美,既沒有高併發,對資源的共享和競爭也是比較混亂。總之:
a. 每次new Thread新建對象性能差。
b. 線程缺乏統一管理,可能無限制新建線程,相互之間競爭,及可能佔用過多系統資源導致死機或oom。
c. 缺乏更多功能,如定時執行、定期執行、線程中斷。
相比new Thread,Java提供的四種線程池的好處在於:
a. 重用存在的線程,減少對象創建、消亡的開銷,性能佳。
b. 可有效控制最大併發線程數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
c. 提供定時執行、定期執行、單線程、併發數控制等功能。
一、newCacheThreadPool一個無限大並可以緩存的線程池。在之前創建新線程的時刻首先複用已經創建過的空閒線程。
ExecutorService cacheThreadPool = Executors.newCachedThreadPool();
for ( int i = 0 ; i<10 ; i++ ){
final int index = i;
try {
Thread.sleep(index*10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//拿到線程的對象的時候將線程扔到線程池中
cacheThreadPool.execute(new Runnable() {
@Override
public void run() {
Log.d( "newCachedThreadPool" , "" + index );
}
});
}
二、newFixedThreadPool 可以控制最大併發數的線程池。超過最大併發數的線程進入等待隊列。
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
for (int i= 0;i<10;i++){
final int index = i;
fixedThreadPool.execute(new Runnable() {
@Override
public void run() {
try {
Log.d("newFixedThreadPool",index+"");
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
三、newScheduledThreadPool 一個可以定時執行的線程池。
延時1s執行
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.schedule(new Runnable() {
@Override
public void run() {
Log.d("newScheduledThreadPool","延期3秒執行");
}
},3, TimeUnit.SECONDS);
延時1s後每隔3s執行一次
public void initImTimeThreadPool(){
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
Log.d("newScheduledThreadPool","延時1s後每3s執行一次");
}
},1,3,TimeUnit.SECONDS);
}
四、newSingleThreadExecutor 單線程化線程池。支持FIFO、LIFO的優先級執行。
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
for (int i = 0; i<10 ;i++){
final int index = i ;
singleThreadExecutor.execute(new Runnable() {
@Override
public void run() {
try {
Log.d("newSingleThreadExecutor",""+index);
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
那麼問題來了,以上都是講創建線程池並且將線程扔到線程池裏面,那麼,對於在線程池中的線程,我們該如何進行管理呢?
execute()方法實際上是Executor中聲明的方法,在ThreadPoolExecutor進行了具體的實現,這個方法是ThreadPoolExecutor的核心方法,
通過這個方法可以向線程池提交一個任務,交由線程池去執行。
submit()方法是在ExecutorService中聲明的方法,在AbstractExecutorService就已經有了具體的實現,
在ThreadPoolExecutor中並沒有對其進行重寫,這個方法也是用來向線程池提交任務的,但是它和execute()方法不同,
它能夠返回任務執行的結果,去看submit()方法的實現,會發現它實際上還是調用的execute()方法,
只不過它利用了Future來獲取任務執行結果(Future相關內容將在下一篇講述)。
shutdown()和shutdownNow()是用來關閉線程池的。