您好,登錄后才能下訂單哦!
這期內(nèi)容當中小編將會給大家?guī)碛嘘P(guān)如何理解Java常見知識點中的線程池,文章內(nèi)容豐富且以專業(yè)的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。
線程池的基本思想是一種對象池,在程序啟動時就開辟一塊內(nèi)存空間,里面存放了眾多(未死亡)的線程,池中線程執(zhí)行調(diào)度由池管理器來處理。當有線程任務(wù)時,從池中取一個,執(zhí)行完成后線程對象歸池,這樣可以避免反復(fù)創(chuàng)建線程對象所帶來的性能開銷,節(jié)省了系統(tǒng)的資源。
降低資源消耗:通過重復(fù)利用已創(chuàng)建的線程降低線程創(chuàng)建和銷毀造成的消耗(每個線程需要大約1MB內(nèi)存,線程開的越多,消耗的內(nèi)存也就越大,最后死機)。;
提高響應(yīng)速度:當任務(wù)到達時,任務(wù)可以不需要等到線程創(chuàng)建就能立即執(zhí)行;
提高線程的可管理性:線程是稀缺資源,如果無限制的創(chuàng)建,不僅會消耗系統(tǒng)資源,還會降低系統(tǒng)的穩(wěn)定性,使用線程池可以進行統(tǒng)一的分配,調(diào)優(yōu)和監(jiān)控。
對線程進行一些簡單的管理,比如:延時執(zhí)行、定時循環(huán)執(zhí)行的策略等,運用線程池都能進行很好的實現(xiàn)
一個線程池包括以下四個基本組成部分:
線程池管理器(ThreadPool):用于創(chuàng)建并管理線程池,包括 創(chuàng)建線程池,銷毀線程池,添加新任務(wù);
工作線程(WorkThread):線程池中線程,在沒有任務(wù)時處于等待狀態(tài),可以循環(huán)的執(zhí)行任務(wù);
任務(wù)接口(Task):每個任務(wù)必須實現(xiàn)的接口,以供工作線程調(diào)度任務(wù)的執(zhí)行,它主要規(guī)定了任務(wù)的入口,任務(wù)執(zhí)行完后的收尾工作,任務(wù)的執(zhí)行狀態(tài)等;
任務(wù)隊列(taskQueue):用于存放沒有處理的任務(wù)。提供一種緩沖機制。
講到線程池,要重點介紹java.uitl.concurrent.ThreadPoolExecutor類,ThreadPoolExecutor是線程池中最核心的一個類。
我們可以通過ThreadPoolExecutor來創(chuàng)建一個線程池
new ThreadPoolExecutor(corePoolSize, maximumPoolSize,keepAliveTime, milliseconds,runnableTaskQueue, threadFactory,handler);
corePoolSize(線程池的基本大?。?/strong>:當提交一個任務(wù)到線程池時,線程池會創(chuàng)建一個線程來執(zhí)行任務(wù),即使其他空閑的基本線程能夠執(zhí)行新任務(wù)也會創(chuàng)建線程,等到需要執(zhí)行的任務(wù)數(shù)大于線程池基本大小時就不再創(chuàng)建。如果調(diào)用了線程池的prestartAllCoreThreads方法,線程池會提前創(chuàng)建并啟動所有基本線程。
maximumPoolSize(線程池最大大小):線程池允許創(chuàng)建的最大線程數(shù)。如果隊列滿了,并且已創(chuàng)建的線程數(shù)小于最大線程數(shù),則線程池會再創(chuàng)建新的線程執(zhí)行任務(wù)。值得注意的是如果使用了無界的任務(wù)隊列這個參數(shù)就沒什么效果。
runnableTaskQueue(任務(wù)隊列):用于保存等待執(zhí)行的任務(wù)的阻塞隊列。
ThreadFactory:用于設(shè)置創(chuàng)建線程的工廠,可以通過線程工廠給每個創(chuàng)建出來的線程設(shè)置更有意義的名字,Debug和定位問題時非常又幫助。
RejectedExecutionHandler(拒絕策略):當隊列和線程池都滿了,說明線程池處于飽和狀態(tài),那么必須采取一種策略處理提交的新任務(wù)。這個策略默認情況下是AbortPolicy,表示無法處理新任務(wù)時拋出異常。以下是JDK1.5提供的四種策略。n AbortPolicy:直接拋出異常。
keepAliveTime(線程活動保持時間):線程池的工作線程空閑后,保持存活的時間。所以如果任務(wù)很多,并且每個任務(wù)執(zhí)行的時間比較短,可以調(diào)大這個時間,提高線程的利用率。
TimeUnit(線程活動保持時間的單位):可選的單位有天(DAYS),小時(HOURS),分鐘(MINUTES),毫秒(MILLISECONDS),微秒(MICROSECONDS, 千分之一毫秒)和毫微秒(NANOSECONDS, 千分之一微秒)。
向線程池提交任務(wù)
我們可以通過execute()或submit()兩個方法向線程池提交任務(wù),不過它們有所不同
execute()方法沒有返回值,所以無法判斷任務(wù)知否被線程池執(zhí)行成功
threadsPool.execute(new Runnable() { @Override public void run() { // TODO Auto-generated method stub } });
submit()方法返回一個future,那么我們可以通過這個future來判斷任務(wù)是否執(zhí)行成功,通過future的get方法來獲取返回值
try { Object s = future.get(); } catch (InterruptedException e) { // 處理中斷異常 } catch (ExecutionException e) { // 處理無法執(zhí)行任務(wù)異常 } finally { // 關(guān)閉線程池 executor.shutdown(); }
線程池的關(guān)閉
我們可以通過shutdown()或shutdownNow()方法來關(guān)閉線程池,不過它們也有所不同
shutdown的原理是只是將線程池的狀態(tài)設(shè)置成SHUTDOWN狀態(tài),然后中斷所有沒有正在執(zhí)行任務(wù)的線程。
shutdownNow的原理是遍歷線程池中的工作線程,然后逐個調(diào)用線程的interrupt方法來中斷線程,所以無法響應(yīng)中斷的任務(wù)可能永遠無法終止。shutdownNow會首先將線程池的狀態(tài)設(shè)置成STOP,然后嘗試停止所有的正在執(zhí)行或暫停任務(wù)的線程,并返回等待執(zhí)行任務(wù)的列表。
ThreadPoolExecutor執(zhí)行的策略
線程數(shù)量未達到corePoolSize,則新建一個線程(核心線程)執(zhí)行任務(wù)
線程數(shù)量達到了corePools,則將任務(wù)移入隊列等待
隊列已滿,新建線程(非核心線程)執(zhí)行任務(wù)
隊列已滿,總線程數(shù)又達到了maximumPoolSize,就會由(RejectedExecutionHandler)拋出異常
四種拒絕策略
ThreadPoolExecutor.AbortPolicy() 拋出java.util.concurrent.RejectedExecutionException異常
ThreadPoolExecutor.DiscardPolicy() 拋棄當前的任務(wù)
ThreadPoolExecutor.DiscardOldestPolicy() 拋棄舊的任務(wù) (隊列中的第一個任務(wù)替換為當前新進來的任務(wù)執(zhí)行)
ThreadPoolExecutor.CallerRunsPolicy() 重試添加當前的任務(wù),他會自動重復(fù)調(diào)用execute()方法
1. CachedThreadPool():可緩存線程池。
線程數(shù)無限制
有空閑線程則復(fù)用空閑線程,若無空閑線程則新建線程 一定程序減少頻繁創(chuàng)建/銷毀線程,減少系統(tǒng)開銷
CachedThreadPool創(chuàng)建一個可緩存線程池,如果線程池長度超過處理需要,可靈活回收空閑線程,若無可回收,則新建線程
2. FixedThreadPool():定長線程池。
可控制線程最大并發(fā)數(shù)(同時執(zhí)行的線程數(shù))
超出的線程會在隊列中等待
如果某個線程因為執(zhí)行異常而結(jié)束,那么線程池會補充一個新線程。
3. ScheduledThreadPool():
定時線程池。
支持定時及周期性任務(wù)執(zhí)行。
newscheduledThreadPool創(chuàng)建一個定長線程池,支持定時及周期性任務(wù)執(zhí)行。延遲執(zhí)行示例代碼如下.表示延遲1秒后每3秒執(zhí)行一次
public class ThreadPoolExecutorTest3 { public static void main(String[] args) { ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5); scheduledThreadPool.scheduleAtFixedRate(new Runnable() { public void run() { System.out.println(Thread.currentThread().getName() + ": delay 1 seconds, and excute every 3 seconds"); } }, 1, 3, TimeUnit.SECONDS);// 表示延遲1秒后每3秒執(zhí)行一次 } }
4. SingleThreadExecutor():單線程化的線程池。
有且僅有一個工作線程執(zhí)行任務(wù)
所有任務(wù)按照指定順序執(zhí)行,即遵循隊列的入隊出隊規(guī)則
newSingleThreadExecutor創(chuàng)建一個單線程化的線程池,它只會用唯一的工作線程來執(zhí)行任務(wù),保證所有任務(wù)按照指定順序(FIFO, LIFO, 優(yōu)先級)執(zhí)行,如果這個唯一的線程因為異常結(jié)束,那么會有一個新的線程來替代它。此線程池保證所有任務(wù)的執(zhí)行順序按照任務(wù)的提交順序執(zhí)行
通過繼承線程池并重寫線程池的beforeExecute,afterExecute和terminated方法,我們可以在任務(wù)執(zhí)行前,執(zhí)行后和線程池關(guān)閉前干一些事情。如監(jiān)控任務(wù)的平均執(zhí)行時間,最大執(zhí)行時間和最小執(zhí)行時間等。這幾個方法在線程池里是空方法。
上述就是小編為大家分享的如何理解Java常見知識點中的線程池了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關(guān)知識,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。