458
人物
原子循环计数器
现实当中很多场景,需要进行轮训服务,比如轮训在10个日志文件当中写日志,在10台机器上轮训的去调用以实现负载均衡,常规的做法,如tomcat的Poller线程轮训选择,就采用
Math.abs(pollerRotater.incrementAndGet()) % pollers.length
此地需要取原子自增的绝对值模以poller线程数,那是否有更好的实现呢?
public class CycleAtomicInteger { private final static long PARK_TIME = 1000L * 1000; private AtomicInteger counter = new AtomicInteger(0); private int range; public CycleAtomicInteger(int range) { if (range < 2) throw new IllegalArgumentException(); this.range = range; } /** * 获取下个原子值 * * @return */ public int next() { for (;;) { int c = counter.get(); int next = (c + 1) % range; if (counter.compareAndSet(c, next)) { return c; } else { LockSupport.parkNanos(PARK_TIME); } } } }
这样就可以快速的实现rr的效果,同时也避免了abs的过程,至于LockSupport.parkNanos(PARK_TIME);加了这个后,4个线程执行2亿次的计算,我本机从原来的16s减少到4s,至于为什么要加这个,可参见更快的AtomicInteger
当然,这样设计会存在cas的aba问题,但对当前的case需求,其实是满足的,也不存在问题
最后更新:2017-05-23 18:02:22