在項目中如果使用發簡訊這個功能,一般會把發簡訊這個動作變成非同步,因為大部分情況下,簡訊到底是發送成功或者失敗,都不能影響主流程。當然像發送MQ訊息等操作也是可以封裝成非同步作業的。 使用基本的New Thread
如果想一個操作變成非同步,可以直接new thread,然後在run方法中實現業務操作即可。例如:
new Thread(new Runnable() { public void run() { //發簡訊、發MQ訊息等 } });
但是這種方式有幾個缺點。 每次都會new一個線程,執行完後銷毀,不能複用; 如果系統的並發量剛好比較大,需要大量線程,那麼這種每次new的方式會搶資源的。 ThreadPoolExecutor
我們可以使用jdk1.5中的ThreadPoolExecutor來封裝非同步作業。ThreadPoolExecutor的好處是可以做到線程複用,並且使用盡量少的線程去執行更多的任務,效率和效能都相當不錯。demo代碼如下:
public class ThreadPool { private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(8, 12, 30, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(50000), new ThreadPoolExecutor.AbortPolicy()); public static ThreadPoolExecutor getThreadPool() { return threadPool; }}參數介紹
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { } corePoolSize:當workQueue隊列中的元素還未到達最大值時,corePoolSize表示的池中線程數量的最大值; maximumPoolSize:線程池中允許的最大線程數; keepAliveTime:當前池中的線程數如果超過了corePoolSize,那麼超出那些線程如果空閑太久了,應該需要銷毀的。keepAliveTime就是的是這些線程的最大空閑時間; unit:keepAliveTime的時間單位; workQueue:當池中線程數的數量已經達到了corePoolSize,那麼如果請求還繼續過來,會把請求對應的task放入隊列中;
handler:當workQueue滿了,池中的線程數又達到了maximumPoolSize,這個時候已經沒有多餘的資源處理請求了,需要RejectedExecutionHandler 來處理。拒絕處理或者丟棄任務等等。 執行過程
當沒有請求時,線程池中沒有任何線程; 當有請求時,建立線程,一直到池中的線程數等於corePoolSize; 如果請求太多,需要更多的線程來處理的話,ThreadPoolExecutor選擇把請求放入隊列中,暫時不建立線程; 如果workQueue也滿了,ThreadPoolExecutor會繼續建立線程,直到線程數量跟maximumPoolSize相等; 線程數達到maximumPoolSize了,同時workQueue也慢了,就只能把請求丟給RejectedExecutionHandler 來處理。 備忘
使用ThreadPoolExecutor時,需要根據自己的業務情況,適當的指定參數值的大小。