我想实现一个简单的循环负载均衡器,我想要' getServer'方法线程安全:
private static int[] servers = new int[]{0,1,2};
private static int SERVER_INDEX = 0;
//not fast enough?
public synchronized static int getServer() {
SERVER_INDEX++;
if (SERVER_INDEX >= servers.length - 1) {
SERVER_INDEX = 0;
}
return servers[SERVER_INDEX];
}
private static AtomicInteger SERVER_INDEX_2 = new AtomicInteger(0);
//not thread-safe and will get Exception
public static int getServer2() {
int index = SERVER_INDEX_2.getAndIncrement();
if (index >= servers.length - 1) {
SERVER_INDEX_2.set(0);
}
return servers[index]; //ERROR! arrayIndexOutOfRange
}
private static AtomicLong SERVER_INDEX_3 = new AtomicLong(0);
//thread-safe but...
public static int getServer3() {
long longIndex = SERVER_INDEX_3.getAndIncrement();
long index = longIndex % servers.length;
int intIndex = (int)index;
return servers[intIndex]; //May overflow someday! 'intIndex can be negative'...
}
我认为上述所有内容都不够好。有一种简单而优雅的方法吗?
答案 0 :(得分:0)
在Java 8中,您可以使用getAndAccumulate,如下所示:
private static AtomicInteger ind = new AtomicInteger(0);
public static int getServer() {
return servers[ind.getAndAccumulate(servers.length, (cur, n)->cur >= n-1 ? 0 : cur+1)];
}