演算法~如何將整數按著型別分段
阿新 • • 發佈:2022-03-16
如何將整數按著型別分段,即有個數字3,它可以表示型別1裡的計數3;有個數字10005,它可以表求型別2裡的5,這種設計主要用在型別和數字關係緊密的場景,向ThreadPoolExecutor
用到了這種設計,ThreadPoolExecutor中的runState和workCount機制,實現在一個int變數中,儲存這兩種資訊,如何實現的?`
位運算基礎
位運算保證的運算的結果是2的n次冪
// i = 10: 十進位制 是10,二進位制是 1010 // i << 1: 左移1位,二進位制變為 10100,轉換位十進位制 則是 20,相當於乘以2的1次數 // i = 20: 十進位制 是20,二進位制是 10100 // i >> 1: 右移1位,二進位制變為 1010,轉換位十進位制 則是 10,相當於除以2的1次數 // i << 3:相當於乘以2的3次方;i >> 3:相當於除以2的3次數
- 使用程式碼進行說明
@Slf4j public class BitTest { private static final int COUNT_BITS = Integer.SIZE - 3; // 低29位的容量 private static final int CAPACITY = (1 << COUNT_BITS) - 1; // 把runState理解為區間段,每個區間段都有獨立的workCount,它們都是成對出現的 private static final int RUNNING = -1 << COUNT_BITS;//-1*536,870,912 private static final int SHUTDOWN = 0 << COUNT_BITS; //0*536,870,912=0 private static final int STOP = 1 << COUNT_BITS; //1*536,870,912 private static final int TIDYING = 2 << COUNT_BITS;//2*536,870,912 private static final int TERMINATED = 3 << COUNT_BITS;//3*536,870,912 private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0)); // 執行狀態[高3位] private static int runStateOf(int c) { return c & ~CAPACITY; } // 工作數[低29位] private static int workerCountOf(int c) { return c & CAPACITY; } // 狀態和工作數生成的ctl,是一個數字,每個區間段通過runState來區分 private static int ctlOf(int rs, int wc) { return rs | wc; } /** * 一個數,存兩個狀態的值,高3位存runState,低29位儲存workCount */ @Test public void runStateWorkCount() { //閾值,將一個int32的資料分成了幾個區間段,而這個狀態值與遞增數的臨界點就是cap,如int32的低10位存遞增,高22位存狀態 int cap = Integer.SIZE - 22;//10 cap=(1 << cap) - 1; //向左移10位減1,到了高22位 //狀態數 int status = 1 << cap; //第一個區間段,可以從0開始的 //遞增數 int indexCount = 5; log.debug("-------------------------------------------"); int saveValue=ctlOf(indexCount, status); log.debug("需要持久化的數:{} | {}={}", indexCount, status, saveValue); log.debug("獲取狀態數:{},獲取對應的遞增數:{}", runStateOf(saveValue),workerCountOf(saveValue)); log.debug("-------------------------------------------"); ctl.set(ctlOf(RUNNING, 256)); log.debug("ctl={}", ctl.get()); System.out.println("runStateOf=" + runStateOf(ctl.get())); System.out.println("workerCountOf=" + workerCountOf(ctl.get())); } }
- 結果
14:05:19.107 [main] DEBUG com.lind.common.aesh.command.BitTest - -2147483648 & ~1023=-2147483648 14:05:19.111 [main] DEBUG com.lind.common.aesh.command.BitTest - 5 & 1023=5 14:05:19.111 [main] DEBUG com.lind.common.aesh.command.BitTest - ------------------------------------------- 14:05:19.111 [main] DEBUG com.lind.common.aesh.command.BitTest - 需要持久化的數:5 | -2147483648=-2147483643 14:05:19.111 [main] DEBUG com.lind.common.aesh.command.BitTest - 獲取狀態數:-2147483648,獲取對應的遞增數:5 14:05:19.111 [main] DEBUG com.lind.common.aesh.command.BitTest - ------------------------------------------- 14:05:19.111 [main] DEBUG com.lind.common.aesh.command.BitTest - ctl=-536870656
- 結論
將我們的數字分成了若干的區間,通過位運算計算這個數,並存儲這個數及解析這個數