7

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

 2 years ago
source link: https://www.cnblogs.com/lori/p/16012565.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

如何将整数按着类型分段,即有个数字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
  • 结论
    将我们的数字分成了若干的区间,通过位运算计算这个数,并存储这个数及解析这个数

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK