看ForkJoin源码的时候,发现了一个有趣的用法,在每一个WorkQueue里面都有一个array来存放任务,如果要取一个具体的任务,首先这个array的长度一定是2的次幂,这时候就可以用unsafe里的arrayBaseOffset获取到第一个元素的偏移地址,然后和arrayIndexScale(获取数组里每一个元素的大小)联合使用便可以获得某一个下标的具体位置:
long i = (((a.length - 1) & b) << ASHIFT) + ABASE;
这里((a.length - 1) & b)就是下标索引,大家可以试试如果保证a.length是2的次幂,b是某个具体下标,这样的操作就是下标索引,ASHIFT其实就是2的几次方,ASHIFT是通过如下算法算出来的:
ASHIFT = 31 - Integer.numberOfLeadingZeros(scale);
这样如果是4,算出来的就是2,*4和左移2是一样的效果。最后再加上ABASE即可。 当然我们也可以通过:
long i = ABASE+scale*b(具体下标)
但是大佬们一般都喜欢用位运算的方式使代码更快。