java執行緒池以及newCachedThreadPool使用過程中的問題
阿新 • • 發佈:2019-01-24
為什麼要用執行緒池?原因很簡單,效能好,而且不用自己費心費力的管理執行緒
1、執行緒池基本說明及定義
從JDK 1.5開始,添加了Executors工具類,這個類定義了Executor、ExecutorService、ScheduledExecutorService、ThreadFactory、Calable類的工廠和實用方法。在Executors類的原始碼註釋中,這樣寫道:
該類包含:
1. 提供能夠建立並返回設定了常用配置的ExecutorService的方法2. 提供能夠建立並返回設定了常用配置的ScheduledExecutorService的方法
3. 提供能夠建立並返回一個經過包裝(禁用了特定的實現方法,僅僅暴露ExecutorService的實現)的ExecutorService方法
4. 提供能夠建立並返回能修改新建執行緒狀態的ThreadFactory的方法
5. 提供能夠建立並返回非閉包形式的Callable,因此能夠在需要Callable的執行方法中使用
Executors類提供4種執行緒池:
1. newFixedThreadPool:建立固定大小
相比下面將要介紹的newCachedThreadPool,newFixedThreadPool可控制執行緒最大併發數,當執行緒池中的執行緒數達到其設定大小時,其餘新建立的執行緒會在LinkedBlockingQueue佇列中等待。當執行緒池中的某個執行緒失敗而終止時,新的執行緒會代替它執行剩下的任務。執行緒池中的執行緒只有在顯式呼叫shutdown函式時才會退出執行緒池 2. newCachedThreadPool:建立可快取執行緒池,當執行緒池中的執行緒空閒時間超過60s,便會終止該空閒執行緒並從快取執行緒池中移除public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory); }
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
該執行緒池可根據需要,建立新執行緒,從上面程式碼中可以看出,其執行緒數最大可為Integer.MAX_VALUE,如果控制不好,使用該執行緒池可能導致執行緒建立過多,反而影響效能。因此,可以注意一下該執行緒池的使用場景:對於大量短暫非同步任務的程式來說,使用該執行緒池能夠大大提高效能
3. newSingleThreadExecutor,建立單執行緒的執行緒池
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(),
threadFactory));
}
當該單執行緒在shutdown之前由於失敗而終止時,將會有新的執行緒來代替它執行剩下任務。加入到該執行緒池裡的執行緒會按順序執行,一個時刻保證只有一個執行緒在執行
4. newScheduledThreadPool,建立固定大小且能夠執行定時或週期性任務的執行緒池 public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
public static ScheduledExecutorService newScheduledThreadPool(
int corePoolSize, ThreadFactory threadFactory) {
return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory);
}
2、執行緒池使用
使用過程很簡單,下面以newFixedThreadPool為例:建立一個大小為3的一個執行緒池,一共10個執行緒任務,每個任務會輸出當前執行執行緒的名稱,然後睡眠500ms(睡眠的目的是使結果更清晰)public class TestNewFixedThreadPool {
public static void main(String[] args) {
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(3);
for (int i = 0; i < 10; ++i) {
newFixedThreadPool.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
}
}
結果:
pool-1-thread-1
pool-1-thread-3
pool-1-thread-2
pool-1-thread-2
pool-1-thread-1
pool-1-thread-3
pool-1-thread-1
pool-1-thread-2
pool-1-thread-3
pool-1-thread-3
從輸出結果可以看出,線上程池中一共有3個執行緒,原因是該執行緒池控制了最大併發執行緒數為3。當使用newCachedThreadPool時,由於存在睡眠時長,很有可能會有10個執行緒來執行