您好,登錄后才能下訂單哦!
這篇文章主要介紹“使用Java線程池的方法步驟”,在日常操作中,相信很多人在使用Java線程池的方法步驟問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”使用Java線程池的方法步驟”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
1.頻繁創(chuàng)建和銷毀單個線程,浪費資源,并且還會出現(xiàn)頻繁GC
2.缺乏統(tǒng)一管理,各線程相互競爭
ThreadPoolExecutor有四個重載的構(gòu)造方法,我們這里來說說參數(shù)最多的那一個重載的構(gòu)造方法,這樣大家就知道其他方法參數(shù)的含義了,如下:
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
各參數(shù)詳細(xì)說明:
這里是7個參數(shù)(我們在開發(fā)中用的更多的是5個參數(shù)的構(gòu)造方法),OK,那我們來看看這里七個參數(shù)的含義:
corePoolSize 線程池中核心線程的數(shù)量
maximumPoolSize 線程池中最大線程數(shù)量
keepAliveTime 非核心線程的超時時長,當(dāng)系統(tǒng)中非核心線程閑置時間超過keepAliveTime之后,則會被回收。如果ThreadPoolExecutor的allowCoreThreadTimeOut屬性設(shè)置為true,則該參數(shù)也表示核心線程的超時時長
unit 第三個參數(shù)的單位,有納秒、微秒、毫秒、秒、分、時、天等
workQueue 線程池中的任務(wù)隊列,該隊列主要用來存儲已經(jīng)被提交但是尚未執(zhí)行的任務(wù)。存儲在這里的任務(wù)是由ThreadPoolExecutor的execute方法提交來的。
threadFactory 為線程池提供創(chuàng)建新線程的功能,這個我們一般使用默認(rèn)即可
handler 拒絕策略,當(dāng)線程無法執(zhí)行新任務(wù)時(一般是由于線程池中的線程數(shù)量已經(jīng)達(dá)到最大數(shù)或者線程池關(guān)閉導(dǎo)致的),默認(rèn)情況下,當(dāng)線程池?zé)o法處理新線程時,會拋出一個RejectedExecutionException。
workQueue介紹
1.ArrayBlockingQueue:這個表示一個規(guī)定了大小的BlockingQueue,ArrayBlockingQueue的構(gòu)造函數(shù)接受一個int類型的數(shù)據(jù),該數(shù)據(jù)表示BlockingQueue的大小,存儲在ArrayBlockingQueue中的元素按照FIFO(先進(jìn)先出)的方式來進(jìn)行存取。
2.LinkedBlockingQueue:這個表示一個大小不確定的BlockingQueue,在LinkedBlockingQueue的構(gòu)造方法中可以傳一個int類型的數(shù)據(jù),這樣創(chuàng)建出來的LinkedBlockingQueue是有大小的,也可以不傳,不傳的話,LinkedBlockingQueue的大小就為Integer.MAX_VALUE,源碼如下:
3.PriorityBlockingQueue:這個隊列和LinkedBlockingQueue類似,不同的是PriorityBlockingQueue中的元素不是按照FIFO來排序的,而是按照元素的Comparator來決定存取順序的(這個功能也反映了存入PriorityBlockingQueue中的數(shù)據(jù)必須實現(xiàn)了Comparator接口)。
4.SynchronousQueue:這個是同步Queue,屬于線程安全的BlockingQueue的一種,在SynchronousQueue中,生產(chǎn)者線程的插入操作必須要等待消費者線程的移除操作,Synchronous內(nèi)部沒有數(shù)據(jù)緩存空間,因此我們無法對SynchronousQueue進(jìn)行讀取或者遍歷其中的數(shù)據(jù),元素只有在你試圖取走的時候才有可能存在。我們可以理解為生產(chǎn)者和消費者互相等待,等到對方之后然后再一起離開。
拒絕策略
AbortPolicy:直接拒絕,并拋出異常,這也是默認(rèn)的策略。
CallerRunsPolicy:直接讓調(diào)用execute方法的線程去執(zhí)行此任務(wù)。
DiscardOldestPolicy:丟棄最老的未處理的任務(wù),然后重新嘗試執(zhí)行當(dāng)前的新任務(wù)。
DiscardPolicy:直接丟棄當(dāng)前任務(wù),但是不拋異常
當(dāng)線程數(shù)量未達(dá)到corePoolSize的時候,就會創(chuàng)建新的線程來執(zhí)行任務(wù)。
當(dāng)核心線程數(shù)已滿,就會把任務(wù)放到阻塞隊列。
當(dāng)隊列已滿,并且未達(dá)到最大線程數(shù),就會新建非核心線程來執(zhí)行任務(wù)(重要)。
當(dāng)隊列已滿,并且達(dá)到了最大線程數(shù),則選擇一種拒絕策略來執(zhí)行。
1.FixedThreadPool
固定大小的線程池,可以指定線程池的大小,該線程池corePoolSize和maximumPoolSize相等,阻塞隊列使用的是LinkedBlockingQueue,大小為整數(shù)最大值。
該線程池中的線程數(shù)量始終不變,當(dāng)有新任務(wù)提交時,線程池中有空閑線程則會立即執(zhí)行,如果沒有,則會暫存到阻塞隊列。對于固定大小的線程池,不存在線程數(shù)量的變化。
同時使用無界的LinkedBlockingQueue來存放執(zhí)行的任務(wù)。當(dāng)任務(wù)提交十分頻繁的時候,LinkedBlockingQueue迅速增大,存在著耗盡系統(tǒng)資源的問題。
而且在線程池空閑時,即線程池中沒有可運行任務(wù)時,它也不會釋放工作線程,還會占用一定的系統(tǒng)資源,需要shutdown
2.SingleThreadExecutor
可以看到阻塞隊例 使用的是LinkedBolckingQueue,且默認(rèn)大小為Integer.MAX_VALUE,這樣的話,如果有大量請求到來,會放入到這個任務(wù)隊列里,可能會導(dǎo)致OOM;
3.Executors.newCachedThreadPool()
可緩存線程池,先查看線程池中有沒有以前建立的線程,如果有就直接使用,如果沒有新建一個線程加入線程池中,可緩存線程池
通常用于執(zhí)行一些生存期很短的異步型任務(wù);線程池為無限大,當(dāng)執(zhí)行當(dāng)前任務(wù)時上一個任務(wù)已經(jīng)完成,會復(fù)用執(zhí)行上一個任務(wù)的線程,而不用每次新建線程
緩存的線程默認(rèn)存活60秒。線程的核心池corePoolSize大小為0,核心池最大為Integer.MAX_VALUE,阻塞隊列使用的是SynchronousQueue。
是一個直接提交的阻塞隊列,他總會迫使線程池增加新的線程去執(zhí)行新的任務(wù)。
在沒有任務(wù)執(zhí)行時,當(dāng)線程的空閑時間超過keepAliveTime(60秒),則工作線程將會終止被回收,當(dāng)提交新任務(wù)時,
如果沒有空閑線程,則創(chuàng)建新線程執(zhí)行任務(wù),會導(dǎo)致一定的系統(tǒng)開銷。
如果同時又大量任務(wù)被提交,而且任務(wù)執(zhí)行的時間不是特別快,那么線程池便會新增出等量的線程池處理任務(wù),這很可能會很快耗盡系統(tǒng)的資源。
4.ScheduledThreadPool
創(chuàng)建一個定長線程池,支持定時及周期性任務(wù)執(zhí)行
定時線程池,該線程池可用于周期性地去執(zhí)行任務(wù),通常用于周期性的同步數(shù)據(jù)。
scheduleAtFixedRate:是以固定的頻率去執(zhí)行任務(wù),周期是指每次執(zhí)行任務(wù)成功執(zhí)行之間的間隔。
schedultWithFixedDelay:是以固定的延時去執(zhí)行任務(wù),延時是指上一次執(zhí)行成功之后和下一次開始執(zhí)行的之前的時間。
通過上述源碼分析,我們發(fā)現(xiàn)newFixedThreadPool和newSingleThreadExecutor方法他們都使用了LinkedBlockingQueue的任務(wù)隊列,LinkedBlockingQueue的默認(rèn)大小為Integer.MAX_VALUE。而newCachedThreadPool中定義的線程池大小為Integer.MAX_VALUE。
所以阿里禁止使用Executors創(chuàng)建線程池的原因就是FixedThreadPool和SingleThreadPool的請求隊列長度為Integer.MAX_VALUE,可能會堆積大量的請求,從而導(dǎo)致OOM。
CachedThreadPool允許的創(chuàng)建線程數(shù)量為Integer.MAX_VALUE,可能會創(chuàng)建大量的線程,從而導(dǎo)致OOM。
1.shutDown() 關(guān)閉線程池,不影響已經(jīng)提交的任務(wù)
2.shutDownNow() 關(guān)閉線程池,并嘗試去終止正在執(zhí)行的線程
3.allowCoreThreadTimeOut(boolean value) 允許核心線程閑置超時時被回收
4.單例模式創(chuàng)建線程池
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.*;
/**
* 異步任務(wù)處理器
*/
public class AsyncTaskExecutor {
/** 線程池保持ALIVE狀態(tài)線程數(shù) */
public static final int CORE_POOL_SIZE = 10;
/** 線程池最大線程數(shù) */
public static final int MAX_POOL_SIZE = 40;
/** 空閑線程回收時間 */
public static final int KEEP_ALIVE_TIME = 1000;
/** 線程池等待隊列 */
public static final int BLOCKING_QUEUE_SIZE = 1000;
/** 業(yè)務(wù)請求異步處理線程池 */
private static final ThreadPoolExecutor processExecutor = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.MICROSECONDS,
new LinkedBlockingQueue<Runnable>(BLOCKING_QUEUE_SIZE),
new TreadFactoryBuilder.setNameFormat("boomoom-thread-pool-%d").build(),
new TreadPoolExecutor.DiscardPolicy());
private AsyncTaskExecutor() {};
/**
* 異步任務(wù)處理
*
* @param task 任務(wù)
*/
public void execute(Runnable task) {
processExecutor.submit(task);
}
}
懶漢式和饑漢式區(qū)別
1.餓漢式是線程安全的,在類創(chuàng)建的同時就已經(jīng)創(chuàng)建好一個靜態(tài)的對象供系統(tǒng)使用,以后不再改變。
2.懶漢式如果想要線程安全必須用雙重檢驗鎖并且對象還必須是volatile,防止對象指令重排
到此,關(guān)于“使用Java線程池的方法步驟”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。