四種線程池分別是:newCachedThreadPool、newFixedThreadPool 、newScheduledThreadPool 和newSingleThreadExecutor ,下面對這幾個線程池一一講解。java
源碼:緩存
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
newCachedThreadPool的方法中是返回一個ThreadPoolExecutor實例,從源碼中能夠看出該線程池的特色:架構
一、該線程池的核心線程數量是0,線程的數量最高能夠達到Integer 類型最大值;ide
二、建立ThreadPoolExecutor實例時傳過去的參數是一個SynchronousQueue實例,說明在建立任務時,若存在空閒線程就複用它,沒有的話再新建線程。學習
三、線程處於閒置狀態超過60s的話,就會被銷燬。this
用法:spa
public static void main(String[] args) { //定義ExecutorService實例 ExecutorService cachedThreadPool = Executors.newCachedThreadPool(); for (int i = 0; i < 10; i++) { final int index = i; try { Thread.sleep(index * 1000); } catch (InterruptedException e) { e.printStackTrace(); } //調用execute方法 cachedThreadPool.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread() + ":" + index); } }); } }
上面的代碼由於每次循環都是隔一秒執行,這個時間足夠以前的線程工做完畢,並在新循環中複用這個線程,程序的運行結果以下:線程
Thread[pool-1-thread-1,5,main]:0 Thread[pool-1-thread-1,5,main]:1 Thread[pool-1-thread-1,5,main]:2 Thread[pool-1-thread-1,5,main]:3 Thread[pool-1-thread-1,5,main]:4 Thread[pool-1-thread-1,5,main]:5 Thread[pool-1-thread-1,5,main]:6 Thread[pool-1-thread-1,5,main]:7 Thread[pool-1-thread-1,5,main]:8 Thread[pool-1-thread-1,5,main]:9
源碼:code
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
線程池特色:接口
一、線程池的最大線程數等於核心線程數,而且線程池的線程不會由於閒置超時被銷燬。
二、使用的列隊是LinkedBlockingQueue,表示若是當前線程數小於核心線程數,那麼即便有空閒線程也不會複用線程去執行任務,而是建立新的線程去執行任務。若是當前執行任務數量大於核心線程數,此時再提交任務就在隊列中等待,直到有可用線程。
用法:
public static void main(String[] args) { ExecutorService cachedThreadPool = Executors.newFixedThreadPool(3); for (int i = 0; i < 10; i++) { final int index = i; try { Thread.sleep(index * 1000); } catch (InterruptedException e) { e.printStackTrace(); } cachedThreadPool.execute(new Runnable() { @Override public void run() { System.out.println(Thread.currentThread() + ":" + index); } }); } }
定義一個線程數爲3的線程池,循環10次執行,能夠發現運行的線程永遠只有三個,結果以下:
Thread[pool-1-thread-1,5,main]:0 Thread[pool-1-thread-2,5,main]:1 Thread[pool-1-thread-3,5,main]:2 Thread[pool-1-thread-1,5,main]:3 Thread[pool-1-thread-2,5,main]:4 Thread[pool-1-thread-3,5,main]:5 Thread[pool-1-thread-1,5,main]:6 Thread[pool-1-thread-2,5,main]:7 Thread[pool-1-thread-3,5,main]:8 Thread[pool-1-thread-1,5,main]:9
源碼:
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
從源碼就能夠看出,該線程池基本就是隻有一個線程數的newFixedThreadPool,它只有一個線程在工做,全部任務按照指定順序執行。
用法:
和newFixedThreadPool相似,只是一直只有一個線程在工做,這裏就不貼代碼了。
源碼:
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); } public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
newScheduledThreadPool的方法不是直接返回一個ThreadPoolExecutor實例,而是經過有定時功能的ThreadPoolExecutor,也就是ScheduledThreadPoolExecutor
來返回ThreadPoolExecutor實例,從源碼中能夠看出:
一、該線程池能夠設置核心線程數量,最大線程數與newCachedThreadPool同樣,都是Integer.MAX_VALUE。
二、該線程池採用的隊列是DelayedWorkQueue,具備延遲和定時的做用。
用法:
public static void main(String[] args) { ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3); //延遲3秒執行,只執行一次 ((ScheduledExecutorService) scheduledThreadPool).schedule(new Runnable() { @Override public void run() { System.out.println("延遲========"); } },3,TimeUnit.SECONDS); //延遲1秒後每隔兩秒執行一次 ((ScheduledExecutorService) scheduledThreadPool).scheduleAtFixedRate(new Runnable() { @Override public void run() { System.out.println("執行============"); } },1,2,TimeUnit.SECONDS); //單位是秒 }
四種線程池的使用就說到這裏了,值得說明的是,除了上面的參數外,Executors類中還給這四種線程池提供了可傳ThreadFactory
的重載方法,如下是它們的源碼:
public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory) { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory)); } public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory) { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), threadFactory); } public static ScheduledExecutorService newScheduledThreadPool( int corePoolSize, ThreadFactory threadFactory) { return new ScheduledThreadPoolExecutor(corePoolSize, threadFactory); } public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), threadFactory); }
ThreadFactory是一個接口類,也就是咱們常常說的線程工廠,只有一個方法,能夠用於建立線程:
Thread newThread(Runnable r);
默認狀況下,ThreadPoolExecutor構造器傳入的ThreadFactory
參數是Executors類中的defaultThreadFactory(),至關於一個線程工廠,幫咱們建立了線程池中所需的線程。在此我向你們推薦一個架構學習交流圈:830478757 幫助突破瓶頸 提高思惟能力
除此以外,咱們也能夠自定義ThreadFactory,並根據本身的須要來操做線程,下面是實例代碼:
public static void main(String[] args) { ExecutorService service = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>(), new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); System.out.println("我是線程" + r); return t; } } ); //用lambda表達式編寫方法體中的邏輯 Runnable run = () -> { try { Thread.sleep(1000); System.out.println(Thread.currentThread().getName() + "正在執行"); } catch (InterruptedException e) { e.printStackTrace(); } }; for (int i = 0; i < 5; i++) { service.submit(run); } //這裏必定要作關閉 service.shutdown(); }
運行代碼後,控制行會輸出五行 「我是線程java.util.concurrent.ThreadPoolExecutor。。。。。」的信息,也證實了咱們自定義的ThreadFactory起到了做用。