newCachedThreadPool線程池:
理解:
1).newCachedThreadPool可以創建一個無限大小的線程池(實際上是一個可緩存線程池)。
可以通過Executors的靜態方法創建線程池:
public static ExecutorService newCachedThreadPool() 或者
public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) 。
2).返回的是ExecutorService對象線程池。
3).newCachedThreadPool在執行過程中通常會創建與所需數量相同的線程,然后在它回收舊線程時停止創建新線程,因此它是合理的Executor的首選。
只有當這種方式會引發問題時(內存溢出),你才需要切換到newFixedThreadPool()。
4).無限制不代表不可以復用線程,假設說一開始進來10個任務,啟動了10個線程,10個任務結束后,然后又來了5個任務(線程還沒被回收),
這時候會復用之前的線程,不會新起線程,這就達到了使用“線程池”的意義。
使用場景:
1. 耗時較短的任務。
2. 任務處理速度 > 任務提交速度 ,這樣才能保證不會不斷創建新的進程,避免內存被占滿。
1. 耗時較短的任務。
2. 任務處理速度 > 任務提交速度 ,這樣才能保證不會不斷創建新的進程,避免內存被占滿。
//首先看Executors中通過newCachedThreadPool創建線程池的方法的源碼 //此方法是通過new一個ThreadPoolExecutor來創建的 //這個構造方法有5個參數: //第一個參數corePoolSize(核心池大小)為0, //第二個參數maximumPoolSize(最大線程池大小)為Integer.MAX_VALUE無限大,源碼中是:public static final int MAX_VALUE = 0x7fffffff; //第三個參數keepAliveTime(線程存貨的時間)是60秒,意味着線程空閑時間超過60秒就會被殺死。 //第五個參數采用SynchronousQueue裝等待的任務,這個阻塞隊列沒有存儲空間,這意味着只要有請求到來,就必須要找到一條工作線程處理他, // 如果當前沒有空閑的線程,那么就會再創建一條新的線程。 public class Executors { public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } } //ThreadPoolExecutor類中此構造函數源碼: public class ThreadPoolExecutor extends AbstractExecutorService { public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); } }
下面是Thinking in java書中的例子:
public class LiftOff implements Runnable { protected int countDown = 5; private static int taskCount = 0; private final int id = taskCount++; public LiftOff() { } public LiftOff(int countDown) { this.countDown = countDown; } public String status() { return "# " + id + " ( " + (countDown > 0 ? countDown : "LiftOff !") + " )"; } @Override public void run() { while (countDown-- > 0) { System.out.println(status()); Thread.yield(); } } }
public class CachedThreadPool { public static void main(String[] args) { ExecutorService executorService = Executors.newCachedThreadPool(); for (int i = 0; i < 3; i++) { executorService.execute(new LiftOff()); } } } 結果: # 2 ( 4 ) # 0 ( 4 ) # 1 ( 4 ) # 2 ( 3 ) # 0 ( 3 ) # 2 ( 2 ) # 1 ( 3 ) # 2 ( 1 ) # 0 ( 2 ) # 2 ( LiftOff ! ) # 1 ( 2 ) # 0 ( 1 ) # 1 ( 1 ) # 0 ( LiftOff ! ) # 1 ( LiftOff ! )