Мой LoadBalancer:
Код: Выделить всё
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class LoadBalancer1 {
private final List instanceList = new ArrayList();
private static final int MAX_SIZE = 10;
private final LoadBalancerStrategy strategy;
private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
private static final ReentrantReadWriteLock.ReadLock readLock = lock.readLock();
private static final ReentrantReadWriteLock.WriteLock writeLock = lock.writeLock();
public LoadBalancer1(LoadBalancerStrategy strategy) {
this.strategy = strategy;
}
public boolean register(String instance) {
writeLock.lock();
try {
if (size() == MAX_SIZE) {
return false;
}
if (instanceList.contains(instance)) {
return false;
}
instanceList.add(instance);
return true;
} finally {
writeLock.unlock();
}
}
public String get() {
readLock.lock();
try {
return this.strategy.get(this.instanceList);
}finally {
readLock.unlock();
}
}
public int size() {
readLock.lock();
try {
return this.instanceList.size();
} finally {
readLock.unlock();
}
}
}
interface LoadBalancerStrategy {
String get(List instances);
}
class RandomStrategy implements LoadBalancerStrategy {
@Override
public String get(List instances) {
if (instances.isEmpty()) {
return null;
}
return instances.get(ThreadLocalRandom.current().nextInt(instances.size()));
}
}
class RoundRobinStrategy implements LoadBalancerStrategy {
private final AtomicInteger currentIndex = new AtomicInteger(0);
@Override
public String get(List instances) { // Synchronize access
if (instances.isEmpty()) {
return null;
}
int index = currentIndex.getAndUpdate(i -> (i + 1) % instances.size());
return instances.get(index);
}
}
Код: Выделить всё
@RepeatedTest(100)
void should_keep_round_robin_pattern_in_concurrent_environment() throws InterruptedException, ExecutionException {
// given
loadBalancerRoundRobin.register("1");
loadBalancerRoundRobin.register("2");
loadBalancerRoundRobin.register("3");
Queue objects = new ArrayBlockingQueue(30);
int threads = Runtime.getRuntime().availableProcessors();
var executorService = Executors.newScheduledThreadPool(threads);
try {
for (int i = 0; i < 30; i++) {
Future submit = executorService.submit(() -> loadBalancerRoundRobin.get());
objects.add(submit);
}
} finally {
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.MINUTES);
}
for (int i = 0; i < objects.size() - 3; i += 3) {
assertEquals("1", objects.remove().get());
assertEquals("2", objects.remove().get());
assertEquals("3", objects.remove().get());
}
}
Код: Выделить всё
@BeforeEach
void setUp() {
randomStrategy = new RandomStrategy();
roundRobin = new RoundRobinStrategy();
loadBalancerRandomStrategy = new LoadBalancer1(randomStrategy);
loadBalancerRoundRobin = new LoadBalancer1(roundRobin);
}
Подробнее здесь: https://stackoverflow.com/questions/789 ... tion-fails