国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Executor線程池原理與源碼解讀

wpw / 3352人閱讀

摘要:線程池為線程生命周期的開銷和資源不足問(wèn)題提供了解決方案。狀態(tài)說(shuō)明線程池處于狀態(tài),不接收新任務(wù),不處理已提交的任務(wù),并且會(huì)中斷正在處理的任務(wù)。線程池中允許的最大線程數(shù)。線程池的飽和策略。

線程池為線程生命周期的開銷和資源不足問(wèn)題提供了解決方 案。通過(guò)對(duì)多個(gè)任務(wù)重用線程,線程創(chuàng)建的開銷被分?jǐn)偟搅硕鄠€(gè)任務(wù)上。
線程實(shí)現(xiàn)方式

Thread、Runnable、Callable

//實(shí)現(xiàn)Runnable接口的類將被Thread執(zhí)行,表示一個(gè)基本任務(wù)
public interface Runnable {
    //run方法就是它所有內(nèi)容,就是實(shí)際執(zhí)行的任務(wù)
    public abstract void run();
}
//Callable同樣是任務(wù),與Runnable接口的區(qū)別在于它接口泛型,同時(shí)它執(zhí)行任務(wù)候帶有返回值;
//Callable的使用通過(guò)外層封裝成Future來(lái)使用
public interface Callable {
    //相對(duì)于run方法,call方法帶有返回值
    V call() throws Exception;
}

注意:?jiǎn)?dòng)Thread線程只能用start(JNI方法)來(lái)啟動(dòng),start方法通知虛擬機(jī),虛擬機(jī)通過(guò)調(diào)用器映射到底層操作系統(tǒng),通過(guò)操作系統(tǒng)來(lái)創(chuàng)建線程來(lái)執(zhí)行當(dāng)前任務(wù)的run方法

Executor框架

Executor接口是線程池框架中最基礎(chǔ)的部分,定義了一個(gè)用于執(zhí)行Runnable的execute方法。
從圖中可以看出Exectuor下有一個(gè)重要的子接口ExecutorService,其中定義了線程池的具體行為:

execute(Runnable runnable):執(zhí)行Runnable類型的任務(wù)

submit(task):用來(lái)提交Callable或者Runnable任務(wù),并返回代表此任務(wù)的Future對(duì)象

shutdown():在完成已經(jīng)提交的任務(wù)后封閉辦事,不在接管新的任務(wù)

shutdownNow():停止所有正在履行的任務(wù)并封閉辦事

isTerminated():是一個(gè)鉤子函數(shù),測(cè)試是否所有任務(wù)都履行完畢了

isShutdown():是一個(gè)鉤子函數(shù),測(cè)試是否該ExecutorService是否被關(guān)閉

ExecutorService中的重點(diǎn)屬性:
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

ctl:對(duì)線程池的運(yùn)行狀態(tài)和線程池中有效線程的數(shù)量進(jìn)行控制的一個(gè)字段,它包含兩部分信息:線程池的運(yùn)行狀態(tài)(runState)和線程池內(nèi)有效線程的數(shù)量(workerCount)。

這里可以看到,使用Integer類型來(lái)保存,高3位保存runState,低29位保存workerCount。COUNT_BITS 就是29,CAPACITY 就是1左移29位減1(29個(gè)1),這個(gè)常量表示workerCount的上限值,大約是5億。

ctl相關(guān)方法:

//獲取運(yùn)行狀態(tài)
private static int runStateOf(int c)     { return c & ~CAPACITY; }
//獲取活動(dòng)線程數(shù)
private static int workerCountOf(int c)  { return c & CAPACITY; }
//獲取運(yùn)行狀態(tài)和活動(dòng)線程數(shù)的值
private static int ctlOf(int rs, int wc) { return rs | wc; }

線程池的狀態(tài):

RUNNING = -1 << COUNT_BITS? //高3位為111
SHUTDOWN = 0 << COUNT_BITS? //高3位為000
STOP = 1 << COUNT_BITS? //高3位為001
TIDYING = 2 << COUNT_BITS? //高3位為010
TERMINATED = 3 << COUNT_BITS? //高3位為011

1、RUNNING

狀態(tài)說(shuō)明:線程池處于RUNNING狀態(tài),能夠接收新任務(wù),以及對(duì)已添加的任務(wù)進(jìn)行處理。

狀態(tài)切換:線程池的初始化狀態(tài)是RUNNING。換句話說(shuō),線程池一旦被創(chuàng)建,就處于RUNNING狀態(tài),并且線程池中的任務(wù)數(shù)為0。

2、SHUTDOWN

狀態(tài)說(shuō)明:線程池處于SHUTDOWN狀態(tài),不接收新任務(wù),能夠處理已經(jīng)添加的任務(wù)。

狀態(tài)切換:調(diào)用shutdown()方法時(shí),線程池由RUNNING -> SHUTDOWN。

3、STOP

狀態(tài)說(shuō)明:線程池處于STOP狀態(tài),不接收新任務(wù),不處理已提交的任務(wù),并且會(huì)中斷正在處理的任務(wù)。

狀態(tài)切換:調(diào)用線程池中的shutdownNow()方法時(shí),線程池由(RUNNING or SHUTDOWN) -> STOP。

4、TIDYING

狀態(tài)說(shuō)明:當(dāng)所有的任務(wù)已經(jīng)停止,ctl記錄“任務(wù)數(shù)量”為0,線程池會(huì)變?yōu)門IDYING狀態(tài)。當(dāng)線程池處于TIDYING狀態(tài)時(shí),會(huì)執(zhí)行鉤子函數(shù) terminated()。 terminated()在ThreadPoolExecutor類中是空, 的,若用戶想在線程池變?yōu)門IDYING時(shí),進(jìn)行相應(yīng)處理,可以通過(guò)重載 terminated()函數(shù)來(lái)實(shí)現(xiàn)。

狀態(tài)切換:當(dāng)線程池在SHUTDOWN狀態(tài)下,阻塞隊(duì)列為空并且線程池中執(zhí)行任務(wù)也為空時(shí),就會(huì)由SHUTDOWN -> TIDYING。當(dāng)線程池在STOP狀態(tài)下,線程池中執(zhí)行的任務(wù)為空時(shí),就會(huì)由STOP-> TIDYING。

5、TERMINATED

狀態(tài)說(shuō)明:線程池線程池徹底停止,線程池處于TERMINATED狀態(tài),

狀態(tài)切換:線程池處于TIDYING狀態(tài)時(shí),執(zhí)行完terminated()之后, 就會(huì)由TIDYING->TERMINATED。

線程池使用

RunTask類:

public class RunTask implements Runnable {
    public void run() {
        System.out.println("Thread name:"+Thread.currentThread().getName());
    }
}

ExecutorSample類:

public class ExecutorSample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        for (int i=0;i<20;i++){
            //提交任務(wù)無(wú)返回值
            executor.execute(new RunTask());
            //任務(wù)執(zhí)行完成后有返回值
            Future future = executor.submit(new RunTask());
        }
    }
}

線程池的具體使用:

ThreadPoolExecutor 默認(rèn)線程池

ScheduledThreadPoolExecutor 定時(shí)線程池

ThreadPoolExecutor

線程池的創(chuàng)建:

public ThreadPoolExecutor(int corePoolSize,
                          int maximumPoolSize,
                          long keepAliveTime,
                          TimeUnit unit,
                          BlockingQueue workQueue,
                          ThreadFactory threadFactory,
                          RejectedExecutionHandler handler) {
    this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
         threadFactory, defaultHandler);
}

corePoolSize:線程池中的核心線程數(shù)。當(dāng)提交一個(gè)任務(wù)時(shí),線程池創(chuàng)建一個(gè)新線程執(zhí)行任務(wù),直到當(dāng)前線程數(shù)等于corePoolSize;如果當(dāng)前線程數(shù)為corePoolSize,繼續(xù)提交的任務(wù)被保存到阻塞隊(duì)列中,等待被執(zhí)行;如果執(zhí)行了線程池的prestartAllCoreThreads()方法,線程池會(huì)提前創(chuàng)建并啟動(dòng)所有核心線程。

maximumPoolSize:線程池中允許的最大線程數(shù)。如果當(dāng)前阻塞隊(duì)列滿了,且繼續(xù)提交任務(wù),則創(chuàng)建新的線程執(zhí)行任務(wù),前提是當(dāng)前線程數(shù)小于maximumPoolSize。

keepAliveTime:線程池維護(hù)線程所允許的空閑時(shí)間。當(dāng)線程池中的線程數(shù)量大于corePoolSize時(shí)候,如果這時(shí)候沒(méi)有新的任務(wù)提交,核心線程外的線程不會(huì)立即被銷毀,而是會(huì)等待,直到等待的時(shí)間超過(guò)了keepAliveTime

unit:keepAliveTime的單位時(shí)間

workQueue:用于保存等待被執(zhí)行的任務(wù)的阻塞隊(duì)列,且任務(wù)必須實(shí)現(xiàn)Runnable接口,在JDK中提供了如下阻塞隊(duì)列:

ArrayBlockingQueue:基于數(shù)組結(jié)構(gòu)的有界阻塞隊(duì)列,按FIFO排序任務(wù)。
LinkedBlockingQueue:基于鏈表結(jié)構(gòu)的阻塞隊(duì)列,按FIFO排序任務(wù),吞吐量通常要高于ArrayBlockingQueue。
SynchronousQueue:一個(gè)不存儲(chǔ)元素的阻塞隊(duì)列,每個(gè)插入操作必須等到另一個(gè)線程調(diào)用移除操作,否則插入操作一直處于阻塞狀態(tài),吞吐量通常高于LinkedBlockingQueue。

PriorityBlockingQueue:具有優(yōu)先級(jí)的無(wú)界阻塞隊(duì)列。

threadFactory:ThreadFactory 類型的變量,用來(lái)創(chuàng)建新線程。默認(rèn)使用ThreadFactory.defaultThreadFactory來(lái)創(chuàng)建線程, 會(huì)使新創(chuàng)建線程具有相同的NORM_PRIORITY優(yōu)先級(jí)并且都是非守護(hù)線程,同時(shí)也設(shè)置了線程名稱。

handler:線程池的飽和策略。當(dāng)阻塞隊(duì)列滿了,且沒(méi)有空閑的工作隊(duì)列,如果繼續(xù)提交任務(wù),必須采用一種策略處理該任務(wù).

線程池的監(jiān)控:

public long getTaskCount() //線程池已執(zhí)行與未執(zhí)行的任務(wù)總數(shù)
public long getCompletedTaskCount() //已完成的任務(wù)數(shù)
public int getPoolSize() //線程池當(dāng)前的線程數(shù)
public int getActiveCount() //線程池中正在執(zhí)行任務(wù)的線程數(shù)量
線程池的原理

如果當(dāng)前運(yùn)行的線程少于corePoolSize,則創(chuàng)建新線程來(lái)執(zhí)行任務(wù)(注意這一個(gè)步驟需要獲取全局鎖)。

如果運(yùn)行的線程等于或多于corePoolSize,則將任務(wù)加入BlockingQueue。

如果無(wú)法將任務(wù)加入BlockingQueue(隊(duì)列已滿),則創(chuàng)建新的線程來(lái)處理任務(wù)(注意這一個(gè)步驟需要獲取全局鎖)。

如果創(chuàng)建的新線程將使當(dāng)前運(yùn)行的線程超出maximumPoolSize,任務(wù)將被執(zhí)行飽和策略。

ThreadPoolExecutor 采用上述的設(shè)計(jì)思路,是為執(zhí)行execute()方法時(shí),盡可能避免獲取全局鎖(一個(gè)嚴(yán)重的可伸縮瓶頸)。在ThreadPoolExecutor完成預(yù)熱之后,幾乎所有的execute()方法調(diào)用都是在執(zhí)行步驟2,而步驟2不需要獲取全局鎖。

還沒(méi)關(guān)注我的公眾號(hào)?

掃文末二維碼關(guān)注公眾號(hào)【小強(qiáng)的進(jìn)階之路】可領(lǐng)取如下:

學(xué)習(xí)資料: 1T視頻教程:涵蓋Javaweb前后端教學(xué)視頻、機(jī)器學(xué)習(xí)/人工智能教學(xué)視頻、Linux系統(tǒng)教程視頻、雅思考試視頻教程;

100多本書:包含C/C++、Java、Python三門編程語(yǔ)言的經(jīng)典必看圖書、LeetCode題解大全;

軟件工具:幾乎包括你在編程道路上的可能會(huì)用到的大部分軟件;

項(xiàng)目源碼:20個(gè)JavaWeb項(xiàng)目源碼。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/76253.html

相關(guān)文章

  • 解讀線程

    摘要:為了讓大家理解線程池的整個(gè)設(shè)計(jì)方案,我會(huì)按照的設(shè)計(jì)思路來(lái)多說(shuō)一些相關(guān)的東西。也是因?yàn)榫€程池的需要,所以才有了這個(gè)接口。 線程池是非常重要的工具,如果你要成為一個(gè)好的工程師,還是得比較好地掌握這個(gè)知識(shí)。即使你為了謀生,也要知道,這基本上是面試必問(wèn)的題目,而且面試官很容易從被面試者的回答中捕捉到被面試者的技術(shù)水平。 本文略長(zhǎng),建議在 pc 上閱讀,邊看文章邊翻源碼(Java7 和 Java...

    imccl 評(píng)論0 收藏0
  • dubbo源碼解析(四)注冊(cè)中心——dubbo

    摘要:一該類繼承了類,該類里面封裝了一個(gè)重連機(jī)制,而注冊(cè)中心核心的功能注冊(cè)訂閱取消注冊(cè)取消訂閱,查詢注冊(cè)列表都是調(diào)用了我上一篇文章源碼解析三注冊(cè)中心開篇中講到的實(shí)現(xiàn)方法,畢竟這種實(shí)現(xiàn)注冊(cè)中心的方式是默認(rèn)的方式,不過(guò)推薦使用,這個(gè)后續(xù)講解。 注冊(cè)中心——dubbo 目標(biāo):解釋以為dubbo實(shí)現(xiàn)的注冊(cè)中心原理,解讀duubo-registry-default源碼 dubbo內(nèi)置的注冊(cè)中心實(shí)現(xiàn)方式...

    andot 評(píng)論0 收藏0
  • Java中的線程

    摘要:中的線程池運(yùn)用場(chǎng)景非常廣泛,幾乎所有的一步或者并發(fā)執(zhí)行程序都可以使用。代碼中如果執(zhí)行了方法,線程池會(huì)提前創(chuàng)建并啟動(dòng)所有核心線程。線程池最大數(shù)量線程池允許創(chuàng)建的線程最大數(shù)量。被稱為是可重用固定線程數(shù)的線程池。 Java中的線程池運(yùn)用場(chǎng)景非常廣泛,幾乎所有的一步或者并發(fā)執(zhí)行程序都可以使用。那么線程池有什么好處呢,以及他的實(shí)現(xiàn)原理是怎么樣的呢? 使用線程池的好處 在開發(fā)過(guò)程中,合理的使用線程...

    tomato 評(píng)論0 收藏0
  • 串行還是并行?——記一次 AsyncTask 問(wèn)題排查

    摘要:當(dāng)然,如果你的核心數(shù)夠多,到個(gè)線程的并行度不滿足的話,也可以自定義一個(gè)線程池來(lái)執(zhí)行,不過(guò)這樣的話,要注意自己維護(hù)這個(gè)線程池的初始化,釋放等等操作了。 事情起源于一個(gè)bug排查,一個(gè)AsyncTask的子類,執(zhí)行的時(shí)候發(fā)現(xiàn)onPreExecute方法執(zhí)行了,doInBackground卻遲遲沒(méi)有被調(diào)用。懂AsyncTask一些表面原理的都知道,onPreExecute方法是在主線程執(zhí)行,...

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

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

0條評(píng)論

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