成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

線程池,這一篇或許就夠了

UsherChen / 3307人閱讀

摘要:創(chuàng)建方法最大線程數(shù)即源碼單線程化的線程池有且僅有一個(gè)工作線程執(zhí)行任務(wù)所有任務(wù)按照指定順序執(zhí)行,即遵循隊(duì)列的入隊(duì)出隊(duì)規(guī)則創(chuàng)建方法源碼還有一個(gè)結(jié)合了和,就不介紹了,基本不用。

*本篇文章已授權(quán)微信公眾號(hào) guolin_blog (郭霖)獨(dú)家發(fā)布

為什么用線程池

創(chuàng)建/銷毀線程伴隨著系統(tǒng)開(kāi)銷,過(guò)于頻繁的創(chuàng)建/銷毀線程,會(huì)很大程度上影響處理效率

>例如:
>
>記創(chuàng)建線程消耗時(shí)間T1,執(zhí)行任務(wù)消耗時(shí)間T2,銷毀線程消耗時(shí)間T3
>
>如果T1+T3>T2,那么是不是說(shuō)開(kāi)啟一個(gè)線程來(lái)執(zhí)行這個(gè)任務(wù)太不劃算了!
>
>正好,線程池緩存線程,可用已有的閑置線程來(lái)執(zhí)行新任務(wù),避免了T1+T3帶來(lái)的系統(tǒng)開(kāi)銷

線程并發(fā)數(shù)量過(guò)多,搶占系統(tǒng)資源從而導(dǎo)致阻塞

>我們知道線程能共享系統(tǒng)資源,如果同時(shí)執(zhí)行的線程過(guò)多,就有可能導(dǎo)致系統(tǒng)資源不足而產(chǎn)生阻塞的情況
>
>運(yùn)用線程池能有效的控制線程最大并發(fā)數(shù),避免以上的問(wèn)題

對(duì)線程進(jìn)行一些簡(jiǎn)單的管理

> 比如:延時(shí)執(zhí)行、定時(shí)循環(huán)執(zhí)行的策略等
> 
> 運(yùn)用線程池都能進(jìn)行很好的實(shí)現(xiàn)

線程池ThreadPoolExecutor

既然Android中線程池來(lái)自于Java,那么研究Android線程池其實(shí)也可以說(shuō)是研究Java中的線程池

在Java中,線程池的概念是Executor這個(gè)接口,具體實(shí)現(xiàn)為ThreadPoolExecutor類,學(xué)習(xí)Java中的線程池,就可以直接學(xué)習(xí)他了

對(duì)線程池的配置,就是對(duì)ThreadPoolExecutor構(gòu)造函數(shù)的參數(shù)的配置,既然這些參數(shù)這么重要,就來(lái)看看構(gòu)造函數(shù)的各個(gè)參數(shù)吧

ThreadPoolExecutor提供了四個(gè)構(gòu)造函數(shù)
//五個(gè)參數(shù)的構(gòu)造函數(shù)
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue)

//六個(gè)參數(shù)的構(gòu)造函數(shù)-1
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue,
                          ThreadFactory threadFactory)

//六個(gè)參數(shù)的構(gòu)造函數(shù)-2
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue,
                          RejectedExecutionHandler handler)

//七個(gè)參數(shù)的構(gòu)造函數(shù)
public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler)

我知道你看到這些構(gòu)造函數(shù)和我一樣也是嚇呆了,但其實(shí)一共就7種類型,理解起來(lái)簡(jiǎn)直和理解一周有7天一樣簡(jiǎn)單,而且一周有兩天是周末,其實(shí)也就只有5天需要了解!相信我,畢竟扯皮,我比較擅長(zhǎng)

int corePoolSize => 該線程池中核心線程數(shù)最大值

> **核心線程:**
> 
> 線程池新建線程的時(shí)候,如果當(dāng)前線程總數(shù)小于corePoolSize,則新建的是核心線程,如果超過(guò)corePoolSize,則新建的是非核心線程
> 
> 核心線程默認(rèn)情況下會(huì)一直存活在線程池中,即使這個(gè)核心線程啥也不干(閑置狀態(tài))。
> 
> 如果指定ThreadPoolExecutor的allowCoreThreadTimeOut這個(gè)屬性為true,那么核心線程如果不干活(閑置狀態(tài))的話,超過(guò)一定時(shí)間(時(shí)長(zhǎng)下面參數(shù)決定),就會(huì)被銷毀掉
> 
> 很好理解吧,正常情況下你不干活我也養(yǎng)你,因?yàn)槲铱傆杏玫侥愕臅r(shí)候,但有時(shí)候特殊情況(比如我自己都養(yǎng)不起了),那你不干活我就要把你干掉了

int maximumPoolSize

> 該線程池中**線程總數(shù)最大值**
> 
> 線程總數(shù) = 核心線程數(shù) + 非核心線程數(shù)。核心線程在上面解釋過(guò)了,這里說(shuō)下非核心線程:
> 
> 不是核心線程的線程(別激動(dòng),把刀放下...),其實(shí)在上面解釋過(guò)了

long keepAliveTime

> 該線程池中**非核心線程閑置超時(shí)時(shí)長(zhǎng)**
> 
> 一個(gè)非核心線程,如果不干活(閑置狀態(tài))的時(shí)長(zhǎng)超過(guò)這個(gè)參數(shù)所設(shè)定的時(shí)長(zhǎng),就會(huì)被銷毀掉
> 
> 如果設(shè)置allowCoreThreadTimeOut = true,則會(huì)作用于核心線程

TimeUnit unit

> keepAliveTime的單位,TimeUnit是一個(gè)枚舉類型,其包括:
> 
> 1. NANOSECONDS : 1微毫秒 = 1微秒 / 1000
> 2. MICROSECONDS : 1微秒 = 1毫秒 / 1000
> 3. MILLISECONDS : 1毫秒 = 1秒 /1000
> 4. SECONDS : 秒
> 5. MINUTES : 分
> 6. HOURS : 小時(shí)
> 7. DAYS : 天

BlockingQueue workQueue

> 該線程池中的任務(wù)隊(duì)列:維護(hù)著等待執(zhí)行的Runnable對(duì)象
> 
> 當(dāng)所有的核心線程都在干活時(shí),新添加的任務(wù)會(huì)被添加到這個(gè)隊(duì)列中等待處理,如果隊(duì)列滿了,則新建非核心線程執(zhí)行任務(wù)
> 
> 常用的workQueue類型:
> 
> 1. **SynchronousQueue:**這個(gè)隊(duì)列接收到任務(wù)的時(shí)候,會(huì)直接提交給線程處理,而不保留它如果所有線程都在工作怎么辦?那就新建一個(gè)線程來(lái)處理這個(gè)任務(wù)!所以為了保證不出現(xiàn)<線程數(shù)達(dá)到了maximumPoolSize而不能新建線程>的錯(cuò)誤,使用這個(gè)類型隊(duì)列的時(shí)候,maximumPoolSize一般指定成Integer.MAX_VALUE,即無(wú)限大
> 
> 2. **LinkedBlockingQueue:**這個(gè)隊(duì)列接收到任務(wù)的時(shí)候,如果當(dāng)前線程數(shù)小于核心線程數(shù),則新建線程(核心線程)處理任務(wù);如果當(dāng)前線程數(shù)等于核心線程數(shù),則進(jìn)入隊(duì)列等待。由于這個(gè)隊(duì)列沒(méi)有最大值限制,即所有超過(guò)核心線程數(shù)的任務(wù)都將被添加到隊(duì)列中,這也就導(dǎo)致了maximumPoolSize的設(shè)定失效,因?yàn)榭偩€程數(shù)永遠(yuǎn)不會(huì)超過(guò)corePoolSize
> 
> 3. **ArrayBlockingQueue:**可以限定隊(duì)列的長(zhǎng)度,接收到任務(wù)的時(shí)候,如果沒(méi)有達(dá)到corePoolSize的值,則新建線程(核心線程)執(zhí)行任務(wù),如果達(dá)到了,則入隊(duì)等候,如果隊(duì)列已滿,則新建線程(非核心線程)執(zhí)行任務(wù),又如果總線程數(shù)到了maximumPoolSize,并且隊(duì)列也滿了,則發(fā)生錯(cuò)誤
> 
> 4. **DelayQueue:**隊(duì)列內(nèi)元素必須實(shí)現(xiàn)Delayed接口,這就意味著你傳進(jìn)去的任務(wù)必須先實(shí)現(xiàn)Delayed接口。這個(gè)隊(duì)列接收到任務(wù)時(shí),首先先入隊(duì),只有達(dá)到了指定的延時(shí)時(shí)間,才會(huì)執(zhí)行任務(wù)

ThreadFactory threadFactory

> 創(chuàng)建線程的方式,這是一個(gè)接口,你new他的時(shí)候需要實(shí)現(xiàn)他的`Thread newThread(Runnable r)`方法,一般用不上,**這是星期六,休息**
> 
> 但我還是說(shuō)一句吧(把槍放下...)
> 
> 小伙伴應(yīng)該知道AsyncTask是對(duì)線程池的封裝吧?那就直接放一個(gè)AsyncTask新建線程池的threadFactory參數(shù)源碼吧:
> 
> ```
> new ThreadFactory() {
>     private final AtomicInteger mCount = new AtomicInteger(1);
>     
>     public Thread new Thread(Runnable r) {
>         return new Thread(r,"AsyncTask #" + mCount.getAndIncrement());
>     }
> }
> ```
> 這么簡(jiǎn)單?就給線程起了個(gè)名?!對(duì)啊,所以說(shuō)這是星期六啊,別管他了,雖然我已經(jīng)強(qiáng)迫你們看完了...

RejectedExecutionHandler handler

> 這玩意兒就是拋出異常專用的,比如上面提到的兩個(gè)錯(cuò)誤發(fā)生了,就會(huì)由這個(gè)handler拋出異常,你不指定他也有個(gè)默認(rèn)的
> 
> 拋異常能拋出什么花樣來(lái)?所以這個(gè)星期天不管了,一邊去,根本用不上

新建一個(gè)線程池的時(shí)候,一般只用5個(gè)參數(shù)的構(gòu)造函數(shù)。

向ThreadPoolExecutor添加任務(wù)

那說(shuō)了這么多,你可能有疑惑,我知道new一個(gè)ThreadPoolExecutor,大概知道各個(gè)參數(shù)是干嘛的,可是我new完了,怎么向線程池提交一個(gè)要執(zhí)行的任務(wù)啊?

通過(guò)ThreadPoolExecutor.execute(Runnable command)方法即可向線程池內(nèi)添加一個(gè)任務(wù)

ThreadPoolExecutor的策略

上面介紹參數(shù)的時(shí)候其實(shí)已經(jīng)說(shuō)到了ThreadPoolExecutor執(zhí)行的策略,這里給總結(jié)一下,當(dāng)一個(gè)任務(wù)被添加進(jìn)線程池時(shí):

線程數(shù)量未達(dá)到corePoolSize,則新建一個(gè)線程(核心線程)執(zhí)行任務(wù)

線程數(shù)量達(dá)到了corePools,則將任務(wù)移入隊(duì)列等待

隊(duì)列已滿,新建線程(非核心線程)執(zhí)行任務(wù)

隊(duì)列已滿,總線程數(shù)又達(dá)到了maximumPoolSize,就會(huì)由上面那位星期天(RejectedExecutionHandler)拋出異常

常見(jiàn)四種線程池

如果你不想自己寫一個(gè)線程池,那么你可以從下面看看有沒(méi)有符合你要求的(一般都?jí)蛴昧?,如果有,那么很好你直接用就行了,如果沒(méi)有,那你就老老實(shí)實(shí)自己去寫一個(gè)吧

Java通過(guò)Executors提供了四種線程池,這四種線程池都是直接或間接配置ThreadPoolExecutor的參數(shù)實(shí)現(xiàn)的,下面我都會(huì)貼出這四種線程池構(gòu)造函數(shù)的源碼,各位大佬們一看便知!

來(lái),走起:

CachedThreadPool()

可緩存線程池:

線程數(shù)無(wú)限制

有空閑線程則復(fù)用空閑線程,若無(wú)空閑線程則新建線程

一定程序減少頻繁創(chuàng)建/銷毀線程,減少系統(tǒng)開(kāi)銷

創(chuàng)建方法:

ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

源碼:

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

通過(guò)我上面行云流水談笑風(fēng)生天馬行空滔滔不絕的對(duì)各種參數(shù)的說(shuō)明,這個(gè)源碼你肯定一眼就看懂了,想都不用想(下面三種一樣啦)

FixedThreadPool()

定長(zhǎng)線程池:

可控制線程最大并發(fā)數(shù)(同時(shí)執(zhí)行的線程數(shù))

超出的線程會(huì)在隊(duì)列中等待

創(chuàng)建方法:

//nThreads => 最大線程數(shù)即maximumPoolSize
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(int nThreads);

//threadFactory => 創(chuàng)建線程的方法,這就是我叫你別理他的那個(gè)星期六!你還看!
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(int nThreads, ThreadFactory threadFactory);

源碼:

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

2個(gè)參數(shù)的構(gòu)造方法源碼,不用我貼你也知道他把星期六放在了哪個(gè)位置!所以我就不貼了,省下篇幅給我扯皮

ScheduledThreadPool()

定長(zhǎng)線程池:

支持定時(shí)及周期性任務(wù)執(zhí)行。

創(chuàng)建方法:

//nThreads => 最大線程數(shù)即maximumPoolSize
ExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(int corePoolSize);

源碼:

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
    return new ScheduledThreadPoolExecutor(corePoolSize);
}

//ScheduledThreadPoolExecutor():
public ScheduledThreadPoolExecutor(int corePoolSize) {
    super(corePoolSize, Integer.MAX_VALUE,
          DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
          new DelayedWorkQueue());
}
SingleThreadExecutor()

單線程化的線程池:

有且僅有一個(gè)工作線程執(zhí)行任務(wù)

所有任務(wù)按照指定順序執(zhí)行,即遵循隊(duì)列的入隊(duì)出隊(duì)規(guī)則

創(chuàng)建方法:

ExecutorService singleThreadPool = Executors.newSingleThreadPool();

源碼:

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

還有一個(gè)Executors.newSingleThreadScheduledExecutor()結(jié)合了3和4,就不介紹了,基本不用。

結(jié)語(yǔ)

墻裂建議各位看完本文一定要實(shí)際動(dòng)手去敲一遍都驗(yàn)證一遍,這樣才能很好的掌握知識(shí)

動(dòng)手做,永遠(yuǎn)是學(xué)習(xí)的最好的方式!

end

更多內(nèi)容歡迎訪問(wèn)我的主頁(yè)我的博客

如果我的文章確實(shí)有幫助到你,請(qǐng)不要忘了點(diǎn)一下文末的"?"讓他變成"?"

作為小菜鳥難免很多地方理解不到位,文中若有錯(cuò)誤請(qǐng)直(bu)接(yao)指(ma)出(wo)

寫作不易!

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67049.html

相關(guān)文章

  • SpringBoot中并發(fā)定時(shí)任務(wù)的實(shí)現(xiàn)、動(dòng)態(tài)定時(shí)任務(wù)的實(shí)現(xiàn)(看一篇夠了

    摘要:也是自帶的一個(gè)基于線程池設(shè)計(jì)的定時(shí)任務(wù)類。其每個(gè)調(diào)度任務(wù)都會(huì)分配到線程池中的一個(gè)線程執(zhí)行,所以其任務(wù)是并發(fā)執(zhí)行的,互不影響。 原創(chuàng)不易,如需轉(zhuǎn)載,請(qǐng)注明出處https://www.cnblogs.com/baixianlong/p/10659045.html,否則將追究法律責(zé)任?。?! 一、在JAVA開(kāi)發(fā)領(lǐng)域,目前可以通過(guò)以下幾種方式進(jìn)行定時(shí)任務(wù) 1、單機(jī)部署模式 Timer:jdk中...

    BWrong 評(píng)論0 收藏0
  • 跟著阿里p7一起學(xué)java高并發(fā) - 第18天:玩轉(zhuǎn)java線程一篇夠了

    摘要:高并發(fā)系列第篇文章。簡(jiǎn)單的說(shuō),在使用了線程池之后,創(chuàng)建線程變成了從線程池中獲取一個(gè)空閑的線程,然后使用,關(guān)閉線程變成了將線程歸還到線程池。如果調(diào)用了線程池的方法,線程池會(huì)提前把核心線程都創(chuàng)造好,并啟動(dòng)線程池允許創(chuàng)建的最大線程數(shù)。 java高并發(fā)系列第18篇文章。 本文主要內(nèi)容 什么是線程池 線程池實(shí)現(xiàn)原理 線程池中常見(jiàn)的各種隊(duì)列 自定義線程創(chuàng)建的工廠 常見(jiàn)的飽和策略 自定義飽和策略 ...

    AdolphLWQ 評(píng)論0 收藏0
  • Segmentfault JAVA文章 收藏量TOP20

    摘要:前言從號(hào)開(kāi)始在寫下第一篇文章說(shuō)是筆記還差不多,驚奇地收到有人收藏我的文章的消息,覺(jué)得有點(diǎn)開(kāi)心。突然腦子抽到想爬下里標(biāo)簽下的文章有多少,哪篇被收藏最多,哪篇被點(diǎn)贊最多。。?,F(xiàn)在和大家分享下,收藏量前的文章,被那么多人收藏應(yīng)該是篇值得看的文章。 前言 從18號(hào)開(kāi)始在sf寫下第一篇文章(說(shuō)是筆記還差不多),驚奇地收到有人收藏我的文章的消息,覺(jué)得有點(diǎn)開(kāi)心。突然腦子抽到想爬下sf里JAVA標(biāo)簽下...

    zhaofeihao 評(píng)論0 收藏0
  • 徹底理解Netty,一篇文章夠了

    摘要:如果什么事都沒(méi)得做,它也不會(huì)死循環(huán),它會(huì)將線程休眠起來(lái),直到下一個(gè)事件來(lái)了再繼續(xù)干活,這樣的一個(gè)線程稱之為線程。而請(qǐng)求處理邏輯既可以使用單獨(dú)的線程池進(jìn)行處理,也可以跟放在讀寫線程一塊處理。 Netty到底是什么 從HTTP說(shuō)起 有了Netty,你可以實(shí)現(xiàn)自己的HTTP服務(wù)器,F(xiàn)TP服務(wù)器,UDP服務(wù)器,RPC服務(wù)器,WebSocket服務(wù)器,Redis的Proxy服務(wù)器,MySQL的P...

    yy13818512006 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<