在代码中使用二进制

今天看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的幂次方。但是里面的原理还没有研究明白,希望小伙伴们在下面留言说出你的想法。

后续会继续补充二进制在代码中的应用......


猜你喜欢

转载自blog.csdn.net/dam454450872/article/details/80724770