算法~如何将整数按着类型分段

如何将整数按着类型分段,即有个数字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
  • 结论
    将我们的数字分成了若干的区间,通过位运算计算这个数,并存储这个数及解析这个数
posted @ 2022-03-16 14:18  张占岭  阅读(53)  评论(0编辑  收藏  举报