前言:
在項目中如果使用發(fā)短信這個功能,一般會把發(fā)短信這個動作變成異步的,因為大部分情況下,短信到底是發(fā)送成功或者失敗,都不能影響主流程。當(dāng)然像發(fā)送MQ消息等操作也是可以封裝成異步操作的。
使用基本的New Thread
如果想一個操作變成異步的,可以直接new thread,然后在run方法中實現(xiàn)業(yè)務(wù)操作即可。例如:
1
2
3
4
5
|
new Thread( new Runnable() { public void run() { //發(fā)短信、發(fā)MQ消息等 } }); |
但是這種方式有幾個缺點。
1.每次都會new一個線程,執(zhí)行完后銷毀,不能復(fù)用;
2.如果系統(tǒng)的并發(fā)量剛好比較大,需要大量線程,那么這種每次new的方式會搶資源的。
ThreadPoolExecutor
我們可以使用jdk1.5中的ThreadPoolExecutor來封裝異步操作。ThreadPoolExecutor的好處是可以做到線程復(fù)用,并且使用盡量少的線程去執(zhí)行更多的任務(wù),效率和性能都相當(dāng)不錯。demo代碼如下:
1
2
3
4
5
6
7
8
|
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; } } |
參數(shù)介紹
1
2
3
4
5
6
7
8
|
public ThreadPoolExecutor( int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) { } |
corePoolSize:當(dāng)workQueue隊列中的元素還未到達(dá)最大值時,corePoolSize表示的池中線程數(shù)量的最大值;
maximumPoolSize:線程池中允許的最大線程數(shù);
keepAliveTime:當(dāng)前池中的線程數(shù)如果超過了corePoolSize,那么超出那些線程如果空閑太久了,應(yīng)該需要銷毀的。keepAliveTime就是的是這些線程的最大空閑時間;
unit:keepAliveTime的時間單位;
workQueue:當(dāng)池中線程數(shù)的數(shù)量已經(jīng)達(dá)到了corePoolSize,那么如果請求還繼續(xù)過來,會把請求對應(yīng)的task放入隊列中;
handler:當(dāng)workQueue滿了,池中的線程數(shù)又達(dá)到了maximumPoolSize,這個時候已經(jīng)沒有多余的資源處理請求了,需要RejectedExecutionHandler 來處理。拒絕處理或者丟棄任務(wù)等等。
執(zhí)行過程
當(dāng)沒有請求時,線程池中沒有任何線程;
當(dāng)有請求時,創(chuàng)建線程,一直到池中的線程數(shù)等于corePoolSize;
如果請求太多,需要更多的線程來處理的話,ThreadPoolExecutor選擇把請求放入隊列中,暫時不新建線程;
如果workQueue也滿了,ThreadPoolExecutor會繼續(xù)創(chuàng)建線程,直到線程數(shù)量跟maximumPoolSize相等;
線程數(shù)達(dá)到maximumPoolSize了,同時workQueue也慢了,就只能把請求丟給RejectedExecutionHandler 來處理。
備注
使用ThreadPoolExecutor時,需要根據(jù)自己的業(yè)務(wù)情況,適當(dāng)?shù)闹付▍?shù)值的大小。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
原文鏈接:http://blog.csdn.net/linsongbin1/article/details/51487811