av一区二区在线观看_亚洲男人的天堂网站_日韩亚洲视频_在线成人免费_欧美日韩精品免费观看视频_久草视

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

JAVA線(xiàn)程池專(zhuān)題(概念和作用)

瀏覽:2日期:2022-08-31 10:04:43

線(xiàn)程池的作用

我們?cè)谟靡粋€(gè)東西的時(shí)候,首先得搞明白一個(gè)問(wèn)題。這玩意是干嘛的,為啥要用這個(gè),用別的不行嗎。那么一個(gè)一個(gè)解決這些問(wèn)題

我們之前都用過(guò)數(shù)據(jù)庫(kù)連接池,線(xiàn)程池的作用和連接池有點(diǎn)類(lèi)似,頻繁的創(chuàng)建,銷(xiāo)毀線(xiàn)程會(huì)造成大量的不必要的性能開(kāi)銷(xiāo),所以這個(gè)時(shí)候就出現(xiàn)了一個(gè)東西統(tǒng)一的管理線(xiàn)程,去負(fù)責(zé)線(xiàn)程啥時(shí)候銷(xiāo)毀,啥時(shí)候創(chuàng)建,以及維持線(xiàn)程的狀態(tài),當(dāng)程序需要使用線(xiàn)程的時(shí)候,直接從線(xiàn)程池拿,當(dāng)程序用完了之后,直接把線(xiàn)程放回線(xiàn)程池,不需要去管線(xiàn)程的生命周期,專(zhuān)心的執(zhí)行業(yè)務(wù)代碼就行。

當(dāng)然,如果非要是自己想手動(dòng)new一個(gè)線(xiàn)程來(lái)執(zhí)行,也不是不可以,只是像上面說(shuō)的那樣,第一麻煩,第二開(kāi)銷(xiāo)大,第三不好控制。

控制線(xiàn)程的方法

在說(shuō)到線(xiàn)程池之前,首先要提到一個(gè)創(chuàng)建線(xiàn)程池的工具類(lèi),又或者說(shuō)是工廠(chǎng)類(lèi) Executors 通過(guò)這個(gè)線(xiàn)程可以統(tǒng)一的創(chuàng)建線(xiàn)程,返回的是一個(gè)ExecutorService 類(lèi)這個(gè)類(lèi)中包含了一些對(duì)線(xiàn)程執(zhí)行過(guò)程進(jìn)行管理控制的方法;

void execute(Runnable command); 這個(gè)方法是將任務(wù)提交到線(xiàn)程池進(jìn)行執(zhí)行。這個(gè)方法沒(méi)有返回值。

<T> Future<T> submit(Callable<T> task); 這個(gè)方法最特別的地方是線(xiàn)程執(zhí)行完畢之后是有返回值的,另外方法的參數(shù)可以用Callable也可以為Runnable??梢赃m用于一些后續(xù)的代碼,需要線(xiàn)程執(zhí)行結(jié)果的程序。

下面的示例中,我們創(chuàng)建了一個(gè) ExecutorService 的實(shí)例,提交了一個(gè)任務(wù),然后使用返回的 Future 的 get() 方法等待提交的任務(wù)完成并返回值。

ExecutorService executorService = Executors.newFixedThreadPool(10); Future<String> future = executorService.submit(() -> 'Hello World'); // 一些其它操作 String result = future.get();

在實(shí)際使用時(shí),我們并不會(huì)立即調(diào)用 future.get() 方法,可能會(huì)等待一些時(shí)間,推遲調(diào)用它直到我們需要它的值用于計(jì)算等目的。

ExecutorService 中的 submit() 方法被重載為支持 Runnable 或 Callable ,它們都是功能接口,可以接收一個(gè) lambdas 作為參數(shù)( 從 Java 8 開(kāi)始 ):

使用 Runnable 作為參數(shù)的方法不會(huì)拋出異常也不會(huì)返回任何值 ( 返回 void ) 使用 Callable 作為參數(shù)的方法則可以?huà)伋霎惓R部梢苑祷刂怠?

如果想讓編譯器將參數(shù)推斷為 Callable 類(lèi)型,只需要 lambda 返回一個(gè)值即可。

void shutdown(); 在調(diào)用了shutdown方法之后,線(xiàn)程池就不會(huì)再接收新的任務(wù),此時(shí)線(xiàn)程池還沒(méi)有停止,仍然會(huì)把線(xiàn)程池中國(guó)正在執(zhí)行但是還沒(méi)有執(zhí)行完的任務(wù)繼續(xù)執(zhí)行完畢,那些沒(méi)有開(kāi)始執(zhí)行的任務(wù)則被中斷 List<Runnable> shutdownNow(); 在調(diào)用了shutdownNow方法之后,會(huì)將線(xiàn)程池的狀態(tài)設(shè)置為stop,正在執(zhí)行的任務(wù)則被停止,沒(méi)被執(zhí)行任務(wù)的則返回。

這兩種方法的使用場(chǎng)景:如果線(xiàn)程中的任務(wù)相互之間沒(méi)有什么關(guān)聯(lián)某個(gè)線(xiàn)程的異常對(duì)結(jié)果影響不大。那么所有線(xiàn)程都能在執(zhí)行任務(wù)結(jié)束之后可以正常結(jié)束,程序能在所有task都做完之后正常退出,適合用ShutDown。但是,如果一個(gè)線(xiàn)程在做某個(gè)任務(wù)的時(shí)候失敗,則整個(gè)結(jié)果就是失敗的,其他worker再繼續(xù)做剩下的任務(wù)也是徒勞,這就需要讓他們?nèi)客V巩?dāng)前的工作。這里使用ShutDownNow就可以讓該pool中的所有線(xiàn)程都停止當(dāng)前的工作,從而迫使所有線(xiàn)程執(zhí)行退出。從而讓主程序正常退出。

線(xiàn)程池的分類(lèi)

通過(guò)工廠(chǎng)類(lèi) Executors 通過(guò)這個(gè)線(xiàn)程可以根據(jù)自己的需要統(tǒng)一的創(chuàng)建各種類(lèi)型的線(xiàn)程,線(xiàn)程的分類(lèi)大致分為以下四種:

newSingleThreadExecutor CachedThreadPool newFixedThreadPool newScheduledThreadPool newSingleThreadExecutor 創(chuàng)建一個(gè)單線(xiàn)程的線(xiàn)程池,核心線(xiàn)程和最大線(xiàn)程都為1,因此只會(huì)有一個(gè)工作線(xiàn)程,會(huì)按照指定順序去執(zhí)行,而且空閑時(shí)間為0,說(shuō)明一旦沒(méi)有任務(wù)了,線(xiàn)程就會(huì)被銷(xiāo)毀

public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }

public class SinglePoolDemo { public static void main(String[] args) { ExecutorService pool = Executors.newSingleThreadExecutor();// ExecutorService pool = Executors.newFixedThreadPool(2); for (int i = 0; i < 10; i++) { int finalI = i; pool.execute(() -> { System.out.println(Thread.currentThread().getName()+'----'+ finalI); }); } }}

輸出結(jié)果:

pool-1-thread-1----0pool-1-thread-1----1pool-1-thread-1----2pool-1-thread-1----3pool-1-thread-1----4pool-1-thread-1----5pool-1-thread-1----6pool-1-thread-1----7pool-1-thread-1----8pool-1-thread-1----9

觀(guān)察線(xiàn)程編號(hào),可以發(fā)現(xiàn),自始自終都只有一個(gè)線(xiàn)程在執(zhí)行,并且也是按照順序來(lái)執(zhí)行的,。

JAVA線(xiàn)程池專(zhuān)題(概念和作用)

CachedThreadPool 創(chuàng)建一個(gè)按需創(chuàng)建的線(xiàn)程,核心線(xiàn)程數(shù)為0,有一個(gè)最大線(xiàn)程數(shù)量,意味著可以根據(jù)實(shí)際任務(wù)數(shù)的需要,靈活的創(chuàng)建和管理線(xiàn)程,keepAlive時(shí)間為60s,代表當(dāng)某線(xiàn)程超過(guò)60s空閑的時(shí)候,才會(huì)被銷(xiāo)毀,這個(gè)線(xiàn)程池最特殊的地方在于,同步隊(duì)列最多只能有一個(gè)元素,加入隊(duì)列的線(xiàn)程會(huì)被馬上執(zhí)行。

public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }

public class CachePoolDemo { public static void main(String[] args) { ExecutorService pool = Executors.newCachedThreadPool(); for (int i = 0; i < 20000; i++) { int finalI = i; pool.submit(() -> { System.out.println(Thread.currentThread().getName()+'-------------'+finalI); }); } }}

運(yùn)行結(jié)果部分:

......pool-1-thread-1805-------------19760pool-1-thread-1806-------------19783pool-1-thread-1809-------------19875pool-1-thread-1810-------------19951pool-1-thread-1811-------------19980

以上的代碼我們運(yùn)行了2w次線(xiàn)程任務(wù),如果是按照我們之前的做法的話(huà),我們要new 2w的線(xiàn)程去執(zhí)行。通過(guò)這個(gè)不定長(zhǎng)的線(xiàn)程池,他可以根據(jù)任務(wù)數(shù)來(lái)靈活的分配所創(chuàng)建的線(xiàn)程,如果線(xiàn)程池長(zhǎng)度超過(guò)處理需要,可靈活回收空閑線(xiàn)程,若無(wú)可回收,則新建線(xiàn)程,所以這里只創(chuàng)建了大概1800多個(gè)線(xiàn)程就完成了我們?cè)拘枰猲ew 2w個(gè)線(xiàn)程才能完成的任務(wù),之所以說(shuō)他是靈活分配的是因?yàn)?,可以這樣驗(yàn)證看看,把i的值改為20的話(huà),所創(chuàng)建的線(xiàn)程數(shù)量大概是10以?xún)?nèi),因此是根據(jù)任務(wù)數(shù)量來(lái)自行創(chuàng)建線(xiàn)程數(shù)的,可以保證效率和性能的最大化。

但是經(jīng)過(guò)實(shí)測(cè),這個(gè)靈活性雖然最高,但是性能貌似是相對(duì)比較差的,在兩萬(wàn)任務(wù)數(shù)的條件下,所以他的缺點(diǎn)就是,可能會(huì)創(chuàng)建大量的線(xiàn)程。當(dāng)然線(xiàn)程池這東西是需要根據(jù)自身情況來(lái)選擇的。如果主線(xiàn)程提交任務(wù)的速度遠(yuǎn)遠(yuǎn)大于CachedThreadPool的處理速度,則CachedThreadPool會(huì)不斷地創(chuàng)建新線(xiàn)程來(lái)執(zhí)行任務(wù),這樣有可能會(huì)導(dǎo)致系統(tǒng)耗盡CPU和內(nèi)存資源,所以在使用該線(xiàn)程池是,一定要注意控制并發(fā)的任務(wù)數(shù),否則創(chuàng)建大量的線(xiàn)程可能導(dǎo)致嚴(yán)重的性能問(wèn)題。

JAVA線(xiàn)程池專(zhuān)題(概念和作用)

newFixedThreadPool 可以通過(guò)傳入一個(gè)int參數(shù)來(lái)指定創(chuàng)建一個(gè)定長(zhǎng)的線(xiàn)程池,該線(xiàn)程池的核心線(xiàn)程數(shù)和最大線(xiàn)程數(shù)都是你傳進(jìn)去的參數(shù)的值,存活時(shí)間都為0說(shuō)明只要任務(wù)空閑下來(lái)了,就會(huì)被銷(xiāo)毀,阻塞隊(duì)列的最大值為MAX_VALUE。所以他的缺點(diǎn)是,可能會(huì)將大量的時(shí)間花在處理堆積的請(qǐng)求阻塞隊(duì)列中的線(xiàn)程。

public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }

public class FixedPoolDemo { public static void main(String[] args) { ExecutorService pool = Executors.newFixedThreadPool(10);// ExecutorService pool = Executors.newFixedThreadPool(2); for (int i = 0; i < 1000; i++) { int finalI = i; pool.execute(() -> { System.out.println(Thread.currentThread().getName()+'----'+ finalI); }); } }}

從運(yùn)行結(jié)果可以看出,線(xiàn)程池一直都是維持著十個(gè)線(xiàn)程

.....pool-1-thread-5----882pool-1-thread-1----881pool-1-thread-4----865pool-1-thread-10----989pool-1-thread-3----931pool-1-thread-2----934pool-1-thread-9----910pool-1-thread-6----896

JAVA線(xiàn)程池專(zhuān)題(概念和作用)

newScheduledThreadPool 創(chuàng)建一個(gè)定長(zhǎng)線(xiàn)程池,支持定時(shí)及周期性任務(wù)執(zhí)行。

public ScheduledThreadPoolExecutor(int corePoolSize) { super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedWorkQueue()); }

以上四種線(xiàn)程池,各有優(yōu)劣點(diǎn)

newFixedThreadPool、newSingleThreadExecutor:

主要問(wèn)題是堆積的請(qǐng)求處理隊(duì)列可能會(huì)耗費(fèi)非常大的內(nèi)存,甚至OOM。

newCachedThreadPool、newScheduledThreadPool:

主要問(wèn)題是線(xiàn)程數(shù)最大數(shù)是Integer.MAX_VALUE,可能會(huì)創(chuàng)建數(shù)量非常多的線(xiàn)程,甚至OOM。

阿里線(xiàn)程池規(guī)范

線(xiàn)程池不允許使用 Executors 去創(chuàng)建,而是通過(guò) ThreadPoolExecutor 的方式,這樣的處理方式讓寫(xiě)的同學(xué)更加明確線(xiàn)程池的運(yùn)行規(guī)則,規(guī)避資源耗盡的風(fēng)險(xiǎn)。 FixedThreadPool 和 SingleThreadPool: 允許的請(qǐng)求隊(duì)列長(zhǎng)度為 Integer.MAX_VALUE,可能會(huì)堆積大量的請(qǐng)求,從而導(dǎo)致 OOM。 CachedThreadPool 和 ScheduledThreadPool: 允許的創(chuàng)建線(xiàn)程數(shù)量為 Integer.MAX_VALUE,可能會(huì)創(chuàng)建大量的線(xiàn)程,從而導(dǎo)致 OOM。

總結(jié)

本篇文章首先我們知道了線(xiàn)程池有什么好處,然后了解一些線(xiàn)程的執(zhí)行方法,submit,execute,shutdown以及他們的區(qū)別,用法等等,然后對(duì)幾種線(xiàn)程池做了一個(gè)大概的介紹,以及他們的作用,好處和弊端。如果看的細(xì)心的同學(xué)可以看代碼發(fā)現(xiàn),這些線(xiàn)程池其實(shí)本質(zhì)上都是通過(guò)創(chuàng)建一個(gè) ThreadPoolExecutor ,包括阿里的線(xiàn)程池規(guī)范也是建議用ThreadPoolExecutor ,但是本篇文章只是對(duì)線(xiàn)程池的作用以及分類(lèi)做一個(gè)概述,在下篇文章中,將會(huì)詳細(xì)的講一下ThreadPoolExecutor 。

以上就是JAVA線(xiàn)程池專(zhuān)題(概念和作用)的詳細(xì)內(nèi)容,更多關(guān)于Java線(xiàn)程池的概念和作用的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 中文字幕精品在线 | 中文字幕理伦片免费看 | 狠狠操天天操 | 国产欧美日韩在线视频 | 成人福利视频在线观看 | 精品久久网| 五月婷婷 | 国产剧情一区 | 日韩视频一区二区三区 | 国产天堂av| 狠狠躁日日躁夜夜躁2022麻豆 | 午夜国产在线观看 | 亚洲成人日韩 | 黄色直接看 | 欧美一区二区三区在线视频 | 精品久久久久久 | 激情婷婷丁香 | 欧美一区二区三区的 | 91精品在线播放 | 成年人视频网站 | 精品免费观看 | 综合av网 | 欧美日韩视频在线 | 国产精品一区在线播放 | 黄色小视频在线免费观看 | 成人免费在线视频观看 | 久久一级视频 | 中文字幕精品在线观看 | 黄色录像免费观看 | 欧美精品亚洲精品 | 欧美日韩免费在线 | 97视频在线免费观看 | 欧美一级淫片 | 亚洲午夜久久 | 蜜桃综合网 | 免费的黄色大片 | 五月婷婷丁香网 | 午夜免费在线 | 久久视频一区二区 | 中文字幕偷拍 | 成人动漫免费观看 |