溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何從線程池狀態(tài)管理來看二進(jìn)制操作

發(fā)布時(shí)間:2021-10-21 11:23:28 來源:億速云 閱讀:141 作者:iii 欄目:編程語言

本篇內(nèi)容介紹了“如何從線程池狀態(tài)管理來看二進(jìn)制操作”的有關(guān)知識(shí),在實(shí)際案例的操作過程中,不少人都會(huì)遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

線程池狀態(tài)

首先,為了文章的完整性,我們還是先了解一下線程池的狀態(tài),總結(jié)如下如: 如何從線程池狀態(tài)管理來看二進(jìn)制操作

線程池狀態(tài)分為5種RUNNING、SHUTDOWN、STOPTIDYING、TERMINATED

狀態(tài)代表的含義

  • RUNNING:(運(yùn)行)接收新task,并且處理正在排隊(duì)的task,不中斷正在執(zhí)行的任務(wù)

  • SHUTDOWN:(關(guān)閉)不接受新的task,只處理正在排隊(duì)的task,不中斷正在執(zhí)行的任務(wù)

  • STOP:(停止)不接受新的task,也不處理正在排隊(duì)的task,并且中斷正在執(zhí)行的任務(wù)

  • TIDYING:(整理)所有的task都已經(jīng)終止,上述提到的workCount當(dāng)前活躍線程數(shù)為0,被中斷的任務(wù)和正在排隊(duì)的任務(wù)執(zhí)行當(dāng)前任務(wù)的terminated()鉤子方法

  • TERMINATED:(已終止)標(biāo)識(shí)上述的TIDYING的過程結(jié)束,標(biāo)識(shí)當(dāng)前線程池成功完全停止的狀態(tài)

狀態(tài)轉(zhuǎn)換

大致的流程就是:

RUNNING --> SHUTDOWN --> STOP --> TIDYING --> TERMINATED

上述流程是一個(gè)單方向的順序,也就是說不會(huì)出現(xiàn)類似于STOP --> SHUTDOWN 這種情況;

另外,并不是每一個(gè)狀態(tài)多必須經(jīng)過的;

什么時(shí)候進(jìn)行線程池的狀態(tài)轉(zhuǎn)換呢?

  • RUNNING -> SHUTDOWN:調(diào)用終止線程的方法shutdown()

  • RUNNING or SHUTDOWN -> STOP:調(diào)用shutdownNow()方法后,不管當(dāng)前在RUNNING狀態(tài)還是SHUTDOWN狀態(tài),都是直接轉(zhuǎn)為STOP狀態(tài)

  • SHUTDOWN -> TIDYING:SHUTDOWN狀態(tài)下當(dāng)?shù)却?duì)列 和 正在執(zhí)行的任務(wù) 都為空時(shí),狀態(tài)轉(zhuǎn)為TIDYING

  • STOP -> TIDYING:STOP狀態(tài)下當(dāng)正在執(zhí)行的任務(wù)全部中斷完畢后,狀態(tài)轉(zhuǎn)為TIDYING

  • TIDYING -> TERMINATED:TIDYING狀態(tài)下當(dāng)所有的terminated()鉤子方法全部執(zhí)行完畢后,狀態(tài)轉(zhuǎn)為TERMINATED,線程池關(guān)閉完畢!

管理線程池狀態(tài)

線程池中管理線程池狀態(tài) 和 線程池當(dāng)前活躍線程數(shù),是通過一個(gè)AtomicInteger變量來管理這兩個(gè)狀態(tài)的

什么? 一個(gè)變量管理兩個(gè)這么不相干的狀態(tài)? 對(duì)的;

CTL變量何許人也

讓我們來看一下線程池針對(duì)這部分的實(shí)現(xià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;

    // runState is stored in the high-order bits
    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;

    // Packing and unpacking ctl
    private static int runStateOf(int c)     { return c & ~CAPACITY; }
    private static int workerCountOf(int c)  { return c & CAPACITY; }
    private static int ctlOf(int rs, int wc) { return rs | wc; }
    private static boolean isRunning(int c) {  return c < SHUTDOWN;}

下面,我們來剖析一下上述的實(shí)現(xiàn): 線程池包含5種狀態(tài)如下:具體線程的狀態(tài)代表的含義和狀態(tài)的轉(zhuǎn)換,下面會(huì)有講解:

    private static final int COUNT_BITS = Integer.SIZE - 3;

    private static final int RUNNING    = -1 << COUNT_BITS;
    private static final int SHUTDOWN   =  0 << COUNT_BITS;
    private static final int STOP       =  1 << COUNT_BITS;
    private static final int TIDYING    =  2 << COUNT_BITS;
    private static final int TERMINATED =  3 << COUNT_BITS;

我們知道在java中 int 類型占用4個(gè)字節(jié)32位存儲(chǔ), 上述的幾種狀態(tài): 底層存儲(chǔ)二進(jìn)制為:

1111 1111 1111 1111 1111 1111 1111 1111(-1) 0000 0000 0000 0000 0000 0000 0000 0000(0) 0000 0000 0000 0000 0000 0000 0000 0001(1) 0000 0000 0000 0000 0000 0000 0000 0010(2) 0000 0000 0000 0000 0000 0000 0000 0011(3)

左移<<COUNT_BITS位,COUNT_BITS = Integer.SIZE - 3 也就是 COUNT_BITS = 29,改句子說明用32位的前3位存儲(chǔ)線程池的狀態(tài) 后29位存儲(chǔ)線程池中當(dāng)前線程的個(gè)數(shù), << COUNT_BITS后,變?yōu)橄旅娴亩M(jìn)制:

1110 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0010 0000 0000 0000 0000 0000 0000 0000 0100 0000 0000 0000 0000 0000 0000 0000 0110 0000 0000 0000 0000 0000 0000 0000

我們可以看到,前三位存儲(chǔ)的是 標(biāo)識(shí)線程狀態(tài)的二進(jìn)制

對(duì)于初始化存儲(chǔ)這些狀態(tài)的變量AtomicInteger ctl

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0))

初始化AtomicInteger變量ctl,其中ctlOf(RUNNING, 0) 代碼為:

private static int ctlOf(int rs, int wc) { return rs | wc; }

其中rs標(biāo)識(shí)線程池當(dāng)前狀態(tài),wc為work count標(biāo)識(shí)當(dāng)前工作線程的數(shù)量

上述傳入的是ctlOf(RUNNING, 0) ,當(dāng)前狀態(tài)為RUNING也就是1110 0000 0000 0000 0000 0000 0000 0000 ,wc為0,也就是當(dāng)前工作線程數(shù)為0,其二進(jìn)制為0000 0000 0000 0000 0000 0000 0000 0000 ,做"|"或操作,即

1110 0000 0000 0000 0000 0000 0000 0000 | 0000 0000 0000 0000 0000 0000 0000 0000 = 1110 0000 0000 0000 0000 0000 0000 0000

上述得到的結(jié)果1110 0000 0000 0000 0000 0000 0000 0000就標(biāo)識(shí),當(dāng)前線程池狀態(tài)為RUNNING,線程池活躍線程個(gè)數(shù)為0!

如何管理?

通過上述創(chuàng)建的ctl變量獲取 線程池當(dāng)前狀態(tài) 和 線程中活躍線程個(gè)數(shù) 這兩個(gè)狀態(tài):

獲取線程池當(dāng)前狀態(tài),我們可以想一下該如何獲取呢? 現(xiàn)在知道的是ctl的前3位是線程池的狀態(tài),那我們直接構(gòu)造一個(gè)前三位為1,后29位為0的int即可,然后取余就可以了唄,下面看下源碼的實(shí)現(xiàn),就是如此: 使用方法runStateOf

 private static int runStateOf(int c)     { return c & ~CAPACITY; }

其中CAPACITY = (1 << COUNT_BITS) - 1 轉(zhuǎn)化為二進(jìn)制為: 0001 1111 1111 1111 1111 1111 1111 1111 取反"~"后,二進(jìn)制為: 1110 0000 0000 0000 0000 0000 0000 0000 也就是將前3位全部變?yōu)?,后面全部變?yōu)?; 接下來,傳入的ctl變量和~CAPACITY做“&”操作,只會(huì)保留ctl變量的前3位變量,后29位變量全部為0;

例如:一個(gè)標(biāo)識(shí)當(dāng)前狀態(tài)為STOP狀態(tài)的線程池和當(dāng)前活躍線程數(shù)為3的ctl變量為: 0010 0000 0000 0000 0000 0000 0000 0011 和上述得到的1110 0000 0000 0000 0000 0000 0000 0000做“&”操作后得到: 0010 0000 0000 0000 0000 0000 0000 0000 和上述分析的STOP的狀態(tài)的二進(jìn)制相同! 即獲得了當(dāng)前線程的狀態(tài)!

獲取線程池當(dāng)前狀態(tài),也很簡單,我們知道ctl變量的32的后29位存儲(chǔ)的是當(dāng)前活躍線程數(shù),直接構(gòu)造一個(gè)前三位為0,后29位為1的int即可,然后取余就可以獲取到了 使用方法workerCountOf

private static int workerCountOf(int c)  { return c & CAPACITY; }

上述知道CAPACITY為:0001 1111 1111 1111 1111 1111 1111 1111

例如:一個(gè)標(biāo)識(shí)當(dāng)前狀態(tài)為STOP狀態(tài)的線程池和當(dāng)前活躍線程數(shù)為3的ctl變量為: 0010 0000 0000 0000 0000 0000 0000 00110001 1111 1111 1111 1111 1111 1111 1111 取與后: 0000 0000 0000 0000 0000 0000 0000 0011 標(biāo)識(shí)當(dāng)前線程池中活躍線程數(shù)量為3!

一些方法

1、計(jì)算ctl的值

方法:

private static int ctlOf(int rs, int wc) { return rs | wc; }

其中,入?yún)s代表當(dāng)前線程狀態(tài),wc代表當(dāng)前活躍線程數(shù),取“|”或即可 上述代碼不出現(xiàn)問題的前提是:rs只使用的前3位,wc只使用了后29位!

2、判斷當(dāng)前線程池是否正在運(yùn)行

方法:

private static boolean isRunning(int c) {  return c <小于SHUTDOWN;}值即可!

上述我們知道,5中狀態(tài)只有RUNNING小于0,SHUTDOWN狀態(tài)等于0,其他的都是大于0的,所以我們直接把給定的ctl值小于SHUTDOWN值即可!

“如何從線程池狀態(tài)管理來看二進(jìn)制操作”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI