本文共 935 字,大约阅读时间需要 3 分钟。
感谢同事[孙棋]的投稿
现实当中很多场景,需要进行轮训服务,比如轮训在10个日志文件当中写日志,在10台机器上轮训的去调用以实现负载均衡,常规的做法,如tomcat的Poller线程轮训选择,就采用
1 | Math.abs(pollerRotater.incrementAndGet()) % pollers.length |
此地需要取原子自增的绝对值模以poller线程数,那是否有更好的实现呢?
01 | public class CycleAtomicInteger { |
02 | private final static long PARK_TIME = 1000L * 1000 ; |
03 |
04 | private AtomicInteger counter = new AtomicInteger( 0 ); |
05 |
06 | private int range; |
07 |
08 | public CycleAtomicInteger( int range) { |
09 | if (range < 2 ) |
10 | throw new IllegalArgumentException(); |
11 | this .range = range; |
12 | } |
13 |
14 | /** |
15 | * 获取下个原子值 |
16 | * |
17 | * @return |
18 | */ |
19 | public int next() { |
20 | for (;;) { |
21 | int c = counter.get(); |
22 | int next = (c + 1 ) % range; |
23 | if (counter.compareAndSet(c, next)) { |
24 | return c; |
25 | } else { |
26 | LockSupport.parkNanos(PARK_TIME); |
27 | } |
28 | } |
29 | } |
30 |
31 | } |
这样就可以快速的实现rr的效果,同时也避免了abs的过程,至于LockSupport.parkNanos(PARK_TIME);加了这个后,4个线程执行2亿次的计算,我本机从原来的16s减少到4s,至于为什么要加这个,可参见
当然,这样设计会存在cas的aba问题,但对当前的case需求,其实是满足的,也不存在问题
转载地址:http://qguhl.baihongyu.com/