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


    如何将整数按着类型分段,即有个数字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
    
    • 结论
      将我们的数字分成了若干的区间,通过位运算计算这个数,并存储这个数及解析这个数
  • 相关阅读:
    C++STL——vector
    大数常用计算模板及例题
    在线算法&离线算法
    线段树——hdu1166敌兵布阵
    C++STL——堆栈
    C++STL——优先队列
    C++STL——队列
    图的建立——图的两种存储结构
    Manacher算法——最长回文子串
    HttpClient的几个实现类
  • 原文地址:https://www.cnblogs.com/lori/p/16012565.html
Copyright © 2020-2023  润新知