【線程池簡述】java
線程池中,當須要使用線程時,會從線程池中獲取一個空閒線程,線程完成工做時,不會直接關閉線程,而是將這個線程退回到池子,方便其它人使用。框架
簡而言之,使用線程池後,原來建立線程變成了從線程池得到空閒線程,關閉線程變成了向池子歸還線程。ide
【線程池帶來的好處】性能
1.下降資源消耗,經過重複利用已建立的線程下降線程建立和銷燬形成的性能消耗。ui
2.提升響應速度,當任務到達時,任務能夠不須要等待線程建立,能夠直接執行。spa
3.提升線程的可管理性,線程是稀缺資源,若是無限制地建立,不只會消耗系統資源,還會下降系統的穩定性,使用線程池能夠進行統一的分配,調優和監控。線程
【線程池接口、類關係一覽】 code
【說明】對象
Executor是一個頂級接口,它裏面只聲明一個方法:execute(Runnable command),用來執行傳進去的任務。blog
ExecutorService接口繼承了Executor接口,並聲明瞭一些方法:submit、shutdown、invokeAll等。
AbstractExecutorService抽象類實現了ExecutorService接口,基本實現了ExecutorService接口的全部方法。
ThreadPoolExecutor繼承了類AbstractExecutorService。
【Executors框架】
Executors框架提供了各類類型的線程池,主要有如下幾種工廠方法:
[ newFixedThreadPool()方法 ]
該方法返回一個固定線程數量的線程池。該線程池中的線程數量始終不變,當有一個新的任務提交時,線程池中如有空閒線程,則當即處理。
若沒有空閒線程,則新的任務會被暫存在一個任務隊列中,待有線程空閒時,便處理在任務隊列中的任務。
[ newSingleThreadExecutor()方法 ]
該方法返回一個只有一個線程的線程池。
若多多餘一個任務被提交到該線程池,任務會被保存在一個任務隊列中,待線程空閒,按先入先出順序執行任務。
[ newCachedThreadPool()方法 ]
該方法返回一個可具實際狀況調整線程數量的線程池,線程池的線程數量不肯定,但如有空閒線程能夠複用,則會有優先使用而能夠複用線程。若全部線程均在工做,又有新的任務提交,則會建立新的現場處理任務。全部線程在當前任務執行完畢後,將返回線程池進行復用。
[ newSingleThreadScheduledExecutor()方法 ]
該方法返回一個ScheduleExecutorService對象,線程池大小爲1。
ScheduleExecutorService接口在ExecutorService接口之上擴張了在給定時間執行某任務的功能,如:在某個固定的延時以後執行,或者週期性執行某個任務。
[ newScheduleThreadPool()方法 ]
該方法返回一個ScheduleExecutorService對象,但該線程池能夠指定線程數量。
【固定大小的線程池——newFixedThreadPool()】
package com.test.executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class ExecutorDemo1 { public static void main(String[] args) { MyTask task = new MyTask(); ExecutorService es = Executors.newFixedThreadPool(5); //建立固定線程數大小爲5的線程池 for(int i=0;i<10;i++){ //依次向線程池提交了10個任務 es.submit(task); } } } class MyTask implements Runnable{ @Override public void run() { System.out.println(System.currentTimeMillis()+":Thread ID:"+Thread.currentThread().getId()); try{ Thread.sleep(1000); //1秒 }catch(Exception e){ e.printStackTrace(); } } }
【運行結果】
【只有一個線程的線程池——newSingleThreadExecutor()】
package com.test.executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by HigginCui on 2018/4/14. */ public class ExecutorDemo1 { public static void main(String[] args) { MyTask myTask = new MyTask(); //只有一個線程的線程池 ExecutorService es = Executors.newSingleThreadExecutor(); for(int i=0;i<10;i++){ es.submit(myTask); } } } class MyTask implements Runnable{ @Override public void run() { System.out.println(System.currentTimeMillis()/1000 + ":Thread ID:" + Thread.currentThread().getId()); try { Thread.sleep(1000); }catch (Exception e){ e.printStackTrace(); } } }
【運行結果】
【可根據實際狀況調整線程數量的線程池——newCacheThreadPool()】
package com.test.executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Created by HigginCui on 2018/4/14. */ public class ExecutorDemo1 { public static void main(String[] args) { MyTask myTask = new MyTask(); //可根據實際狀況調整線程數量的線程池 ExecutorService es = Executors.newCachedThreadPool(); for(int i=0;i<10;i++){ es.submit(myTask); } } } class MyTask implements Runnable{ @Override public void run() { System.out.println(System.currentTimeMillis()/1000 + ":Thread ID:" + Thread.currentThread().getId()); try { Thread.sleep(1000); }catch (Exception e){ e.printStackTrace(); } } }
【運行結果】
【計劃定時任務——newScheduledThreadPool】
package com.test.executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * Created by HigginCui on 2018/4/14. */ public class ExecutorDemo1 { public static void main(String[] args) { ScheduledExecutorService ses = Executors.newScheduledThreadPool(10); /** * scheduleAtFixedRate方法 :若是前面的任務沒有完成,則調度也不會執行! * scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit); */ ses.scheduleAtFixedRate(new ScheduledTimeTask(), 0, 2, TimeUnit.SECONDS); //設置每定時2s執行一次 } } class ScheduledTimeTask implements Runnable { @Override public void run() { try { //修改這裏的任務執行時間 Thread.sleep(1000); System.out.println( System.currentTimeMillis() / 1000 + " : ThreadId = " + Thread.currentThread().getId()); } catch (Exception e) { e.printStackTrace(); } } }
【設置任務的執行時間爲1s( <定時的2s )的運行結果】
【設置任務的執行時間爲3s( <定時的2s )的運行結果(即代碼改爲Thread.sleep(3000))】