java開源長了, 代碼久了,網上對於線程那是衆說紛紜,一直縈繞我心頭的,jdk線程池好仍是spring線程池好?html
結果發現,spring生命週期管理的線程池,其底層就是私有ThreadPoolExecutor類,spring(具體管理ThreadPoolTaskExecutor類)只是對其一種封裝調用而已;java
而咱們平常使用jdk線程池 - Executor框架, ThreadPoolExecutor是Executor框架的核心實現類;spring
說到底,jdk線程池與spring線程池都是在使用ThreadPollExecutor基礎上開發;json
古老的extend,implment Runnable的實現線程的方式就不說了,也就是測試類寫寫緩存
科普下, jdk8 lambda格式方便快捷的使用多線程
new Thread(() -> System.out.println("線程打印...")).start();
炒的火熱jdk線程池的的核心實現類。app
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) { this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler); }
經過idea源碼方法看到, Executors類下, 有很多快捷建立線程池方法 (idea查看類方法alt+7), 下面介紹經常使用的5種建立方法;框架
FixedThreadPool是可重的固定線程數的線程池。異步
//建立FixedThreadPool Executors.newFixedThreadPool(5); //建立所須要的參數 public static ExecutorService newFixedThreadPool(int nThreads) { //最後調用的都是ThreadPoolExecutor return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
咱們只須要傳如須要建立的線程的數量,也就是線程池的大小。咱們能夠看到構造方法,傳入的線程的數量就是核心線程的數量。也就是FixedThreadPool會建立固定數量核心線程的線程池,而且這些核心線程不會被回收,任務超過線程的數量將存入隊列中。async
該線程池是根據須要去建立線程的。
//建立緩存線程池 Executors.newCachedThreadPool(); //構造方法 public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
咱們能夠看出,這裏面的核心線程數是0,而線程的最大值是Integer.Max_VALUE。閒置超時間是一分鐘。默認隊列能夠保證任務順序的執行。CacheThreadPool適合大量的須要當即處理而且耗時較少的任務。
該類是使用單個線程的線程池。
//建立方法 Executors.newSingleThreadExecutor(); //構造方法 public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
corePoolSize和maximumPoolSize都是1,意味着SingleThreadExecutor只有一個核心線程。其餘的參數和FixedThreadPool同樣。若是已經建立了一個線程再來一個任務的時候會將該任務加入到任務隊列裏面,確保了全部任務的執行順序。
ScheduledThreadPool是一個能實現定是和週期性任務的線程池。
//建立 Executors.newScheduledThreadPool(5); //構造方法 public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS, new DelayedWorkQueue()); } //最後仍是調用的 ThreadPoolExecutor的構造方法。
當執行任務的時候,會先將任務包裝成ScheduledFutrueTask並添加到DelayedWorkQueue裏面,當沒超過corePoolSize的時候,會建立線程,人後去DelayedWorkQueue隊列裏面去拿任務,並非當即的執行。當執行完任務的時候會將ScheduledFutrueTask中的time變量改成下次要執行的時間並放回DelayedWorkQueue中。
springContext.xml配置管理, 其線程池生命週期由spring來管理
<bean id="threadPoolTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <!-- 核心線程數,默認爲1 --> <property name="corePoolSize" value="10" /> <!-- 最大線程數,默認爲Integer.MAX_VALUE --> <property name="maxPoolSize" value="50" /> <!-- 隊列最大長度,通常須要設置值>=notifyScheduledMainExecutor.maxNum;默認爲Integer.MAX_VALUE <property name="queueCapacity" value="1000" /> --> <!-- 線程池維護線程所容許的空閒時間,默認爲60s --> <property name="keepAliveSeconds" value="300" /> <!-- 線程池對拒絕任務(無線程可用)的處理策略,目前只支持AbortPolicy、CallerRunsPolicy;默認爲後者 --> <property name="rejectedExecutionHandler"> <!-- AbortPolicy:直接拋出java.util.concurrent.RejectedExecutionException異常 --> <!-- CallerRunsPolicy:主線程直接執行該任務,執行完以後嘗試添加下一個任務到線程池中,能夠有效下降向線程池內添加任務的速度 --> <!-- DiscardOldestPolicy:拋棄舊的任務、暫不支持;會致使被丟棄的任務沒法再次被執行 --> <!-- DiscardPolicy:拋棄當前任務、暫不支持;會致使被丟棄的任務沒法再次被執行 --> <bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy" /> </property> </bean>
註解又分爲 默認非線程池方式,線程池方式,這裏已線程池方式爲例子
<?xml version="1.0" encoding="UTF-8"?> <!--Spring框架的xml標籤訂義文檔, 可訪問http://www.springframework.org/schema/task/查看最新task組件的xml標籤文檔--> <beans xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation=" http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd"> <!--掃描項目實例化@Component,@Service,@Controller修飾的類--> <context:component-scan base-package="com.your_app" /> <!-- 在代碼中@Async不加參數就會使用task:annotation-driven標籤訂義的executor--> <task:annotation-driven executor="myExecutor"/> <!-- 在代碼中@Async("myExecutor")能夠顯式指定executor爲"myExecutor"--> <task:executor id="myExecutor" pool-size="5-25" queue-capacity="100" rejection-policy="CALLER_RUNS"/> </beans>
@Async void doSomething(String s) { //能夠帶參數! // this will be executed asynchronously }
具體配置歡迎觀看
https://blog.csdn.net/caib1109/article/details/51623089
調用發現,其org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor 類, 源碼查看,
初始化,也是使用ThreadPoolExecutor實現操做,具體指示設置對應的參數值而已;
好了 查看到此結束
文章涉及來源:
SpringMVC異步處理之@Async(附源代碼 - 單元測試經過)
https://blog.csdn.net/caib1109/article/details/51623089
http://www.javashuo.com/article/p-thfurkjh-gd.html
Java多線程-五中線程池分析以及AnsyncTask源碼分析