随机算法简单可行,但不够均衡,在极端情况下会造成一台服务器一直收到请求,另一个服务器一直没收到请求。所以这时候就需要轮询算法。通过依次按顺序调用服务器列表中的服务器即可。例如服务器列表中有ABC三台服务器,一个自增数字,每次自增完取3的余数,0的话取服务器A,1的话取服务器B,2的话取服务器C即可。
public class RandomRobin {
private static AtomicInteger index = new AtomicInteger(0);
public static String getServer(){
ArrayList<String> serverList = new ArrayList<>(ServerIps.LIST);
if (index.get() >= serverList.size()) {
index.set(0);
}
return serverList.get(index.getAndIncrement());
}
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println(getServer());
}
}
}
缺点:循环的时间复杂度是O(n),性能浪费。
多线程情况:
public class RandomRobin {
private static AtomicInteger index = new AtomicInteger(0);
static ReentrantLock lock = new ReentrantLock();
private static ArrayList<String> serverList = new ArrayList<>(ServerIps.LIST);
public static String getServer() {
if (index.get() >= serverList.size()) {
index.set(0);
}
return serverList.get(index.getAndIncrement());
}
public static void main(String[] args) {
CountDownLatch count = new CountDownLatch(5);
CyclicBarrier barrier = new CyclicBarrier(5);
ExecutorService pool = Executors.newFixedThreadPool(5);
for (int i = 0; i < 100; i++) {
pool.execute(() -> {
try {
barrier.await();
lock.lock();
System.out.println("线程" + Thread.currentThread().getName() + "开始执行");
System.out.println(getServer());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
} finally {
lock.unlock();
count.countDown();
}
});
}
try {
count.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
pool.shutdown();
}
}