日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【多线程】ThreadPoolExecutor类源码解析----续(二进制相关运算)

發(fā)布時間:2025/5/22 编程问答 18 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【多线程】ThreadPoolExecutor类源码解析----续(二进制相关运算) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

前言

在之前閱讀 ThreadPoolExecutor 源碼的時候,發(fā)現代碼里用到了一些二進制相關的位運算之類的代碼,看起來有些費勁了,所以現在大概總結了一些筆記,二進制這東西吧,不難,就跟數學一樣,知道規(guī)律,計算公式,就賊簡單,就是二進制轉十進制這種自己算起來比較費勁

但現在又不是考試,所以我選擇計算器!!!!

二進制

計算機采用二進制原因:

  • 首先,二進位計數制僅用兩個數碼。0和1,所以,任何具有二個不同穩(wěn)定狀態(tài)的元件都可用來表示數的某一位。而在實際上具有兩種明顯穩(wěn)定狀態(tài)的元件很多。例如,氖燈的;開關的; 電壓的;紙帶上的有孔無孔,電路中的有信號無信號, 磁性材料的南極北極等等,不勝枚舉。 利用這些截然不同的狀態(tài)來代表數字,是很容易實現的。不僅如此,更重要的是兩種截然不同的狀態(tài)不單有量上的差別,而且是有質上的不同。這樣就能大大提高機器的抗干擾能力,提高可靠性。而要找出一個能表示多于二種狀態(tài)而且簡單可靠的器件,就困難得多了。
  • 其次,二進位計數制的四則運算規(guī)則十分簡單。而且四則運算最后都可歸結為加法運算和移位,這樣,電子計算機中的運算器線路也變得十分簡單了。不僅如此,線路簡化了,速度也就可以提高。這也是十進位計數制所不能相比的 。
  • 第三,在電子計算機中采用二進制表示數可以節(jié)省設備。可 以從理論上證明,用三進位制最省設備,其次就是二進位制。但由于二進位制有包括三進位制在內的其他進位制所沒有的優(yōu)點,所以大多數電子計算機還是采用二進制。此外,由于二進制中只用二個符號 “ 0” 和“1”,因而可用布爾代數來分析和綜合機器中的邏輯線路。 這為設計電子計算機線路提供了一個很有用的工具。
  • 第四,二進制的符號“1”和“0”恰好與邏輯運算中的“對”(true)與“錯”(false)對應,便于計算機進行邏輯運算。

二進制運算

二進制加法有四種情況: 0+0=0,0+1=1,1+0=1,1+1=10(0 進位為1)

二進制乘法有四種情況: 0×0=0,1×0=0,0×1=0,1×1=1

二進制減法有四種情況:0-0=0,1-0=1,1-1=0,0-1=1

二進制除法有兩種情況(除數只能為1):0÷1=0,1÷1=1

java中的位運算

Java定義了位運算符,應用于整數類型(int),長整型(long),短整型(short),字符型(char),和字節(jié)型(byte)等類型。

位運算符作用在所有的位上,并且按位運算。假設a = 60,b = 13;它們的二進制格式表示將如下:

A = 0011 1100B = 0000 1101-----------------A & B = 0000 1100A | B = 0011 1101A ^ B = 0011 0001~A = 1100 0011

下表列出了位運算符的基本運算,假設整數變量 A 的值為 60 和變量 B 的值為 13:

操作符描述例子
如果相對應位都是1,則結果為1,否則為0(A&B),得到12,即0000 1100
如果相對應位都是 0,則結果為 0,否則為 1(A 丨B)得到61,即 0011 1101
^如果相對應位值相同,則結果為0,否則為1(A ^ B)得到49,即 0011 0001
?按位取反運算符翻轉操作數的每一位,即0變成1,1變成0。(?A)得到-61,即1100 0011
<<按位左移運算符。左操作數按位左移右操作數指定的位數。A << 2得到240,即 1111 0000
>>按位右移運算符。左操作數按位右移右操作數指定的位數。A >> 2得到15即 1111
>>>按位右移補零操作符。左操作數的值按右操作數指定的位數右移,移動得到的空位以零填充。A>>>2得到15即0000 1111

測試栗子:

public class BitOperation {public static void main(String[] args) {int a = 60; /* 60 = 0011 1100 */int b = 13; /* 13 = 0000 1101 */int c = 0;c = a & b; /* 12 = 0000 1100 */System.out.println("a & b = " + c );c = a | b; /* 61 = 0011 1101 */System.out.println("a | b = " + c );c = a ^ b; /* 49 = 0011 0001 */System.out.println("a ^ b = " + c );c = ~a; /*-61 = 1100 0011 */System.out.println("~a = " + c );c = a << 2; /* 240 = 1111 0000 */System.out.println("a << 2 = " + c );c = a >> 2; /* 15 = 1111 */System.out.println("a >> 2 = " + c );c = a >>> 2; /* 15 = 0000 1111 */System.out.println("a >>> 2 = " + c );}}

輸出:

a & b = 12a | b = 61a ^ b = 49~a = -61a << 2 = 240a >> 2 = 15a >>> 2 = 15

ThreadPoolExecutor 源碼分析

AtomicInteger ctl

ctl是主要的控制狀態(tài),是一個復合類型的變量,其中包括了兩個概念。

  • workerCount:表示有效的線程數目
  • runState:線程池里線程的運行狀態(tài)

我們來分析一下跟ctl有關的一些源代碼吧,直接上代碼

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));//用來表示線程池數量的位數,很明顯是29,Integer.SIZE=32private static final int COUNT_BITS = Integer.SIZE - 3;//線程池最大數量,2^29 - 1private static final int CAPACITY = (1 << COUNT_BITS) - 1;// runState is stored in the high-order bits//我們可以看出有5種runState狀態(tài),證明至少需要3位來表示runState狀態(tài)//所以高三位就是表示runState了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 ctlprivate 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; }

CAPACITY: 線程最大數量

在這里我們講一下這個線程池最大數量的計算吧,因為這里涉及到源碼以及位移之類的操作,我感覺大多數人都還是不太會這個,因為我一開始看的時候也是不太會的。

private static final int CAPACITY = (1 << COUNT_BITS) - 1;

從代碼我們可以看出,是需要1往左移29位,然后再減去1,那個1往左移29位是怎么計算的呢?

1 << COUNT_BITS1322進制是0000 0000 0000 0000 0000 0000 0000 0001左移29位的話就是0010 0000 0000 0000 0000 0000 0000 0000再進行減一的操作0001 1111 1111 1111 1111 1111 1111 1111也就是說線程池最大數目就是0001 1111 1111 1111 1111 1111 1111 1111

runState:線程池里線程的運行狀態(tài)

正數的原碼、反碼、補碼都是一樣的,在計算機底層,是用補碼來表示的

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;

RUNNING 運行狀態(tài)

可以接受新任務并且處理已經在阻塞隊列的任務,高3位全部是1的話,就是RUNNING狀態(tài)

-1 << COUNT_BITS這里是-1往左移29位,稍微有點不一樣,-1的話需要我們自己算出補碼來-1的原碼1000 0000 0000 0000 0000 0000 0000 0001-1的反碼,負數的反碼是將原碼除符號位以外全部取反1111 1111 1111 1111 1111 1111 1111 1110-1的補碼,負數的補碼就是將反碼+11111 1111 1111 1111 1111 1111 1111 1111關鍵了,往左移29位,所以高3位全是1就是RUNNING狀態(tài)1110 0000 0000 0000 0000 0000 0000 0000

SHUTDOWN 關閉狀態(tài)

不接受新任務,處理已經在阻塞隊列的任務,高3位全是0,就是SHUTDOWN狀態(tài)

0 << COUNT_BITS0的表示00000000 00000000 00000000 00000000往左移2900000000 00000000 00000000 00000000

STOP

不接受新任務,也不處理阻塞隊列里的任務,并且會中斷正在處理的任務,所以高3位是001,就是STOP狀態(tài)

1 << COUNT_BITS1的表示00000000 00000000 00000000 00000001往左移2900100000 00000000 00000000 00000000

TIDYING

所有任務都被中止,workerCount是0,線程狀態(tài)轉化為TIDYING并且調用terminated()鉤子方法,所以高3位是010,就是TIDYING狀態(tài)

2 << COUNT_BITS2322進制00000000 00000000 00000000 00000010往左移2901000000 00000000 00000000 00000000

TERMINATED

terminated()鉤子方法已經完成,所以高3位是110,就是TERMINATED狀態(tài)

3 << COUNT_BITS3322進制00000000 00000000 00000000 00000011往左移2911000000 00000000 00000000 00000000

相關方法介紹

runStateOf

實時獲取runState的方法

private static int runStateOf(int c) { return c & ~CAPACITY; } ~CAPACITY~是按位取反的意思&是按位與的意思而CAPACITY是,高位30,低29位都是1,所以是000 11111 11111111 11111111 11111111取反的話就是111 00000 00000000 00000000 00000000傳進來的c參數與取反的CAPACITY進行按位與操作1、低位290進行按位與,還是2902、高位31,即保持c參數的高3位即高位保持原樣,低29位都是0,這也就獲得了線程池的運行狀態(tài)runState

workerCountOf

獲取線程池的當前有效線程數目

private static int workerCountOf(int c) { return c & CAPACITY; } CAPACITY的322進制是000 11111 11111111 11111111 11111111用入參c跟CAPACITY進行按位與操作1、低29位都是1,所以保留參數c的低29位,也就是有效線程數2、高3位都是0,所以c的高3位也是0這樣獲取出來的便是workerCount的值

ctlOf

原子整型變量ctl的初始化方法

//結合這幾句代碼來看private static final int RUNNING = -1 << COUNT_BITS;private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));private static int ctlOf(int rs, int wc) { return rs | wc; } RUNNING是1110 0000 0000 0000 0000 0000 0000 0000ctlOf是將rs和wc進行按位或的操作初始化的時候是將RUNNING和0進行按位或0322進制是0000 0000 0000 0000 0000 0000 0000 0000所以初始化的ctl是1110 0000 0000 0000 0000 0000 0000 0000

總結

以上是生活随笔為你收集整理的【多线程】ThreadPoolExecutor类源码解析----续(二进制相关运算)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。