问题描述
我正在研究并发性,我想了解为什么在多线程场景中先读后写操作:copyOnWriteArrayList
或 synchronizedList()
会导致非确定性行为。
代码如下:
public class LoadBalancer {
private static final Integer MAX_PROVIDERS_SIZE = 10;
private final List<String> registeredProviders;
private LoadBalancer(List<String> initialProviders) {
if (!(initialProviders.size() == new HashSet<>(initialProviders).size())) {
throw new ProviderAlreadyExists();
}
this.registeredProviders = Collections.synchronizedList(initialProviders);
}
public static LoadBalancer of(List<String> registeredProviders) {
return new LoadBalancer(registeredProviders);
}
public LoadBalancer registerProvider(String provider) {
if (registeredProviders.size() >= MAX_PROVIDERS_SIZE) {
throw new ProvidersLengthExceeded();
} else {
registeredProviders.stream().filter(p -> p.equals(provider))
.findFirst()
.ifPresent(p -> {
throw new ProviderAlreadyExists();
});
registeredProviders.add(provider);
System.out.println("SIZE" + registeredProviders.size());
}
return this;
}
public List<String> getRegisteredProviders() {
return registeredProviders;
}
}
public class ProvidersLengthExceeded extends RuntimeException{
public ProvidersLengthExceeded() {
super("The maximum providers size is 10.");
}
}
public class ProviderAlreadyExists extends RuntimeException{
public ProviderAlreadyExists() {
super("The provider already exists.");
}
}
这是测试:
@Test
public void concurrencyCheck() throws InterruptedException {
List<String> testProviders = IntStream.rangeClosed(0,8).mapToObj(index -> index + "")
.collect(Collectors.toList());
LoadBalancer lb = LoadBalancer.of(testProviders);
ExecutorService service = Executors.newFixedThreadPool(10);
IntStream.range(0,100).forEach(i -> service.submit(() -> {
lb.registerProvider(UUID.randomUUID().toString());
}));
Thread.sleep(10_000);
System.out.println(lb.getRegisteredProviders().size());
}
}
我想要的行为是我不能向列表中添加超过 MAX_PROVIDERS_SIZE
项。
使用上面的代码,我得到以下输出:
SIZE11
SIZE10
SIZE13
SIZE12
13
SIZE10
10
为什么会这样?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)