1. 程式人生 > >ThreadPoolExecutor解析-主要原始碼研究

ThreadPoolExecutor解析-主要原始碼研究

private boolean addWorker(Runnable firstTask, boolean core) {//firstTask:新增一個執行緒並執行這個任務,可空,增加的執行緒從佇列獲取任務;core:是否使用corePoolSize作為上限,否則使用maxmunPoolSize</span>
        retry: //較少使用到的識別符號,用於重試
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))//執行緒狀態非執行並且當非shutdown狀態下任務為空且佇列非空;
                return false;  //判斷條件有點難理解,其實是非執行狀態下(>=SHUTDOWN)或者SHUTDOWN狀態下任務非空(新提交任務)、任務佇列為空,就不可以再新增執行緒了(return false),即SHUTDOWN狀態是可以新增執行緒去執行佇列中的任務;
            for (;;) {
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize)) //實際最大執行緒數是CAPACITY;
                    return false;
                if (compareAndIncrementWorkerCount(c)) //AtomicInteger的CAS操作;
                    break retry;                       //新增執行緒數成功,結束retry(retry下的for迴圈)
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs) //狀態發生改變,重試retry;
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        Worker w = null;
        try {
            final ReentrantLock mainLock = this.mainLock;
            w = new Worker(firstTask); // Worker為內部類,封裝了執行緒和任務,通過ThreadFactory建立執行緒,可能失敗拋異常或者返回null
            final Thread t = w.thread;
            if (t != null) {
                mainLock.lock();
                try {
                    int c = ctl.get();
                    int rs = runStateOf(c);

                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // SHUTDOWN以後的狀態和SHUTDOWN狀態下firstTask為null,不可新增執行緒
                            throw new IllegalThreadStateException();
                        workers.add(w); //儲存到一個HashSet中
                        int s = workers.size();
                        if (s > largestPoolSize)
                            largestPoolSize = s; //記錄最大執行緒數
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);//失敗回退,從wokers移除w,執行緒數減一,嘗試結束執行緒池(呼叫tryTerminate方法,後續解析)
        }
        return workerStarted;
    }
通過以上兩個方法,對於新增任務應該是比較清楚了,新增任務可以說是對執行緒池最常的操作了;

相關推薦

ThreadPoolExecutor解析-主要原始碼研究

private boolean addWorker(Runnable firstTask, boolean core) {//firstTask:新增一個執行緒並執行這個任務,可空,增加的執行緒從佇列獲取任務;core:是否使用corePoolSize作為上限,否則使用maxmunPoolSize</s

PriorityQueue主要原始碼解析

簡介:PriorityQueue優先佇列,是Queue的實現類,但不具有先進先出的特點,而是根據自然排序或者自定義排序進行內部排序的,自然排序下(如儲存Integer,String)會根據從小到大排序,自定義排序可以根據自己定義的比較方法排序。 1.Priority的底層是

週期性執行緒池與主要原始碼解析

之前學習ThreadPool的使用以及原始碼剖析,並且從面試的角度去介紹知識點的解答。今天小強帶來週期性執行緒池的使用和重點原始碼剖析。 ScheduledThreadPoolExecutor ScheduledThreadPoolExecutor:用來處理延時任務或定時任務 定時執行緒池類的類結構圖

線程池ThreadPoolExecutor源碼解讀研究(JDK1.8)

else if whether use rep 類之間關系 sin 如果 一段 源碼解讀 一、什麽是線程池 為什麽要使用線程池?在多線程並發開發中,線程的數量較多,且每個線程執行一定的時間後就結束了,下一個線程任務到來還需要重新創建線程,這樣線程數量特別龐大的

【轉】JDK的Parser來解析Java原始碼詳解

轉自:https://www.jb51.net/article/92989.htm 這篇文章主要介紹了JDK的Parser來解析Java原始碼的相關資料,需要的朋友可以參考下 在JDK中,自帶了一套相關的編譯API,可以在Java中發起編譯流程,解析Java原始檔然後獲取其語法樹,在JDK的

OVS原始碼研究 Datapath進行Packet處理

先把程式碼貼出來,後續再做細化解釋和總結 void ovs_dp_process_packet_with_key(struct sk_buff *skb,    struct sw_flow_key *pkt_key,    bool recirc)

Tinyxml解析過程原始碼分析

        tinyxml是一個優秀的,易用的,開源的xml解析庫,xml解析的最關鍵之處,就是如何將xml檔案內容解析成記憶體中的可用、易用的程式資料---DOM(Document Object Model)樹。DOM其實就是多叉樹,每個節

Mybatis(四):MyBatis核心元件介紹原理解析原始碼解讀 java中代理,靜態代理,動態代理以及spring aop代理方式,實現原理統一彙總

Mybatis核心成員 Configuration        MyBatis所有的配置資訊都儲存在Configuration物件之中,配置檔案中的大部分配置都會儲存到該類中 SqlSession         &

ResNet解析(pytorch原始碼)

首先放一張各層的圖片,整體分為4個layer, pytorch中也是這麼分的 然後這是兩種設計方式,左邊的是用於18,34層的,這樣引數多,右面這種設計方式引數少,適用於更深度的 這裡是這兩個基本塊的程式碼,然後ResNet中把這些塊連線起來就可以組成網路。最重要的程式碼就是下面

rest-framework的APIview原始碼分析,Serializer及解析原始碼分析

rest-framework 1.安裝 方式一:pip3 install djangorestframework 方式二:pycharm圖形化介面安裝 方式三:pycharm命令列下安裝(裝在當前工程所用的直譯器下) 2.djangorestframework的APIVi

區塊鏈100講:以太坊原始碼研究之PoW及共識演算法深究

本講將介紹“挖礦“得到新區塊的整個過程,以及不同共識演算法的實現細節。 1 待挖掘區塊需要組裝 在Ethereum 程式碼中,名為miner的包(package)負責向外提供一個“挖礦”得到的新區塊,其主要結構體的UML關係圖如下圖所示:

jQuery工作原理解析以及原始碼示例

jQuery的開篇聲明裡有一段非常重要的話:jQuery是為了改變javascript的編碼方式而設計的。從這段話可以看出jQuery本身並不是UI元件庫或其他的一般AJAX類庫。jQuery改變javascript編碼方式! 那麼它是如何實現它的宣告的呢?這裡,用以下的一段簡短的使用流程: 1、查詢(建立

從壹開始前後端分離 [ vue + .netcore 補充教程 ] 二八║ Nuxt 基礎:面向原始碼研究Nuxt.js

前言 哈嘍大家週五好,又是一個開開心心的週五了,接下來就是三天小團圓啦,這裡先祝大家節日快樂咯,希望都沒有加班哈哈,今天公司發了月餅,嗯~時間來不及了,上週應該搞個活動抽中幾個粉絲髮月餅的,下次吧,這裡先預告一下,聖誕節活動,給粉絲送蘋果吧哈哈,不過聽起來好 low 呀,大家有好的想法可以下邊評論或者來

分散式服務彈性框架“Hystrix”實踐與原始碼研究(一)

文章初衷 為了應對將來線上(特別是無線端)業務量的成倍增長,後端服務的分散式化程度需要不斷提高,對於服務的延遲和容錯管理將面臨更大挑戰,公司框架和開源團隊選擇內部推廣Netflix的Hystrix,一是為了推進各部門的服務使用覆蓋率,二是為了增加C Sharp語言版本的參與度(目前公司至少三

Cesium距離測量之思路解析原始碼

今天剛好是程式設計師的節日,話不多說祝大家前途一片光明,如果你正在做測量的工具那麼我將會在稍後釋出關與面積測量的文章。 一、實現思路 首先我們需要用到的滑鼠移動事件、單擊事件和雙擊事件,具體功能如下: 1,滑鼠移動事件:判斷是否開始進行測量操作(單擊為開始標誌),如果沒

Cesium面積測量之思路解析原始碼

如果你看過我的距離量測文章,那麼我相信,面積也是你需要測量的吧,那就看看吧。 一、實現思路 首先我們需要用到的滑鼠移動事件、單擊事件和雙擊事件,具體功能如下: 1,滑鼠移動事件:判斷是否開始進行測量操作(單擊為開始標誌),如果沒有,則什麼也不做,如何開始則需要把單擊的座

layoutInflater引數解析原始碼分析

public View inflate(XmlPullParser parser, @Nullable ViewGroup root, boolean attachToRoot) { synchronized (mConstructorArgs) { Trace.tr

開源地圖服務geoserver原始碼研究實踐(IntelliJ IDEA2017匯入工程、環境搭建)

今天我們來學習一下有關開源地圖服務geoserver的原始碼。首先學習這個原始碼還是挺有用的,geoserver是關於spring、寫的一個java服務,此外程式碼裡面應用到很多程式設計套路(設計模式)方面的知識,geoserver地圖服務實現OGC(開放地理資訊聯盟)wms

Volley,Okhttp,Retrofit原始碼研究心得大總結

注:閱讀本篇博文之前建議閱讀上面幾個系列的博文,算是本篇文章的理論儲備。 以前在業餘的時候閱讀過Volley,Okhttp,Retrofit的原始碼,本篇就對他們做一個大總結和鞏固。 1、框架涉及到的設計模式 工廠模式:這個模式很簡單,與其說是一個模式,不如說

定時任務類(原始碼研究

package situopenapi.service.common; import situopenapi.utils.LogUtils; import situopenapi.utils.ThreadFactory; import javax.annotation.PostConstr