今天看netty源码时,看到了EventExecutorChooser(事件执行器选择器,实现从worker reactor线程组中选择一个线程)的创建
@SuppressWarnings("unchecked")
@Override
public EventExecutorChooser newChooser(EventExecutor[] executors) {
if (isPowerOfTwo(executors.length)) {
return new PowerOfTwoEventExecutorChooser(executors);
} else {
return new GenericEventExecutorChooser(executors);
}
}
可以看到通过 isPowerOfTwo(int val)判断reactor线程的个数是否为2的幂次方,来创建Chooser,下面看一下isPowerOfTwo这个方法怎么实现的
private static boolean isPowerOfTwo(int val) {
return (val & -val) == val;
}
可以看到,这个方法很简洁,通过对这个数和它的负数做 “与运算”的结果是否和原数相等为条件来判断该数是否为偶数。
首先回顾一下关于原码、反码、补码的基础知识:
①正数
原码=反码=补码
例如:+6(32位)
原码:0000 0000 0000 0110
反码:0000 0000 0000 0110
补码:0000 0000 0000 0110
②负数
反码:在原码的基础上保证符号位不变,其余按位取反
补码:反码+1
例如:-6
原码:1000 0000 0000 0110
反码:1111 1111 1111 1001
补码:1111 1111 1111 1010
补充一下:计算机中都是以补码的形式存储数据。
所以 6 & -6 = 0000 0000 0000 0110 & 1111 1111 1111 1010 = 0000 0000 0000 0010 不等于6,所以6不是2的幂次方
我们再看一下 4 和 -4
4:
原码:0000 0000 0000 0100
反码:0000 0000 0000 0100
补码:0000 0000 0000 0100
-4:
原码:1000 0000 0000 0100
反码:1111 1111 1111 1011
补码:1111 1111 1111 1100
4 & -4 =0000 0000 0000 0100 & 1111 1111 1111 1100 = 0000 0000 0000 0100 = 4,所以 4是2的幂次方。
结论:我们可以通过 return (val & -val) == val 来判断val是否是2的幂次方。但是里面的原理还没有研究明白,希望小伙伴们在下面留言说出你的想法。
后续会继续补充二进制在代码中的应用......