通常實際開發中常常用到多線程,因此須要使用線程池了,java
ThreadPoolTaskExecutor一般經過XML方式配置,或者經過Executors
的工廠方法進行配置。
XML方式配置代碼以下:交給spring來管理;spring
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> <!-- 核心線程數 --> <property name="corePoolSize" value="4000" /> <!-- 最大線程數 --> <property name="maxPoolSize" value="20000" /> <!-- 隊列最大長度 --> <property name="queueCapacity" value="2000" /> <!-- 線程池維護線程所容許的空閒時間 --> <property name="keepAliveSeconds" value="30" /> <!-- 線程池對拒絕任務(無線程可用)的處理策略 --> <property name="rejectedExecutionHandler"> <bean class="java.util.concurrent.ThreadPoolExecutor$DiscardPolicy" /> </property> </bean>
rejectedExecutionHandler
字段用於配置拒絕策略,經常使用的拒絕策略以下:服務器
AbortPolicy,用於被拒絕任務的處理程序,它將拋出RejectedExecutionException。多線程
CallerRunsPolicy,用於被拒絕任務的處理程序,它直接在execute方法的調用線程中運行被拒絕的任務。併發
DiscardOldestPolicy,用於被拒絕任務的處理程序,它放棄最舊的未處理請求,而後重試execute
。高併發
DiscardPolicy,用於被拒絕任務的處理程序,默認狀況下它將丟棄被拒絕的任務。優化
提交任務spa
無返回值的任務使用execute(Runnable)
線程
有返回值的任務使用submit(Runnable)
日誌
案例代碼
threadPoolTaskExecutor.execute(new Runnable() { public void run() { synchronized (Controller01.class) { try { HttpUtils.get("http://192.168.31.223:8085/test2.do"); System.out.println(System.currentTimeMillis()); } catch (Exception e) { e.printStackTrace(); } } } });
任務處理流程:
在ThreadPoolExecutor中表現爲:
關閉線程池
調用shutdown或者shutdownNow,
二者都不會接受新的任務,並且經過調用要中止線程的interrupt方法來中斷線程,有可能線程永遠不會被中斷,
不一樣之處在於shutdownNow會首先將線程池的狀態設置爲STOP,而後嘗試中止全部線程(有可能致使部分任務沒有執行完)而後返回未執行任務的列表。
而shutdown則只是將線程池的狀態設置爲shutdown,而後中斷全部沒有執行
任務的線程,並將剩餘的任務執行完。
經常使用狀態:
經過繼承線程池,重寫beforeExecute
,afterExecute
和terminated
方法來在線程執行任務前,線程執行任務結束,和線程終結前獲取線程的運行狀況,根據具體狀況調整線程池的線程數量
使用場景
一、當你的任務是非必要的時候。好比記錄操做日誌、通知第三方服務非必要信息等,可使用線程池處理非阻塞任務
二、當你的任務很是耗時時候,能夠採用線程池技術
三、當請求併發很高時,能夠採用線程池技術優化處理
多線程是否是能加快處理速度?
在使用多線程時,必定要知道一個道理:處理速度的最終決定因素是CPU、內存等,在單CPU(不管多少核)上,分配CPU資源的單位是「進程」而不是「線程」。
咱們能夠作一個簡單的試驗:
假設我要拷貝100萬條數據,單CPU電腦,用一個進程,在單線程的狀況下,CPU佔用率爲5%,耗時1000秒。那麼當在這個進程下,開闢10個線程同時去運行,是否是CPU佔用率增長到50%,耗時減小到100秒呢?顯然不是。我實測出來的狀況是這樣的:
「CPU佔用率仍然是5%,總耗時仍然是1000秒。且每一個線程的運行時間也爲1000秒。」
總結:
第一,
看硬件。若是是在比較強大的、多CPU的服務器上運行程序,可使用多線程來提升併發數和執行速度。
可是線程也不宜過多,即便是16個CPU的服務器,同一時間最多也只能真正意義上地併發處理16個線程,多出來的線程仍是要等待。
第二,
看用途。若是你不在意處理速度,僅僅是爲了提升併發處理能力,那麼理所固然地用多線程,
可是若是你僅僅是想提升處理速度,且又是在單CPU機器上運行,那麼多線程並不值得。
若是你的任務很耗時,且能夠一部分、一部分地作,那麼最好不要用多線程(比如搬 磚,單線程一次搬10塊,總共搬10天,但搬一塊算一塊,到第9天的時候,你就搬完90塊磚了;
若是你用10個線程同時去搬磚,一樣要搬10天,可是到第9天的時候,這10個線程100塊磚都「還在路上」,一塊磚都沒搬完!)。