这是一个关于Lombok's @Builder
and @Singular
annotations和线程安全的问题。
作为一个简化的例子,请考虑这个类:
@Builder
public class Avengers {
@Singular
private List<String> members;
}
这会生成一个构建器,在这里我可以这样做:
final Avengers team = Avengers.builder()
.member("Iron Man")
.member("Thor")
.member("Captain America")
.build();
System.out.println(team.getMembers()); // ["Iron Man", "Thor", "Captain America"]
现在针对问题-我想要做的是这样的事情(同样,这是过于简化来说明问题的要点):
final AvengersBuilder teamBuilder = Avengers.builder();
executorService.submit(() -> teamBuilder.member("Iron Man"));
executorService.submit(() -> teamBuilder.member("Thor"));
executorService.submit(() -> teamBuilder.member("Captain America"));
// shutdown and awaitTermination would go here
final Avengers team = teamBuilder.build();
,为什么这是个问题?
生成的构建器不是threadsafe (Lombok通过ArrayList
备份它),因此team.getMembers()
的结果可能是不完整的,或者因此处于不一致的状态。
问题:是否有办法让Lombok生成一个线程安全构建器,让我使用这种“单数”模式?
到目前为止,我的解决方法是避免单数,并创建自己的threadsafe方法,但我希望消除这个样板。
发布于 2022-06-11 00:27:37
这不可能。无论如何,尝试在多个线程之间共享一个构建器是非常不寻常的。您可以更好地存储所有结果,然后迭代它们并将它们全部添加到同一个线程上的构建器中。
List<Future<String>> futures = new ArrayList<>();
futures.add(executorService.submit(() -> "Iron Man"));
futures.add(executorService.submit(() -> "Thor"));
futures.add(executorService.submit(() -> "Captain America"));
// shutdown and awaitTermination would go here
final AvengersBuilder teamBuilder = Avengers.builder();
for (Future<String> future : futures) {
try {
teamBuilder.member(future.get());
}
catch (InterruptedException | ExecutionException e) {
// do something
}
}
final Avengers team = teamBuilder.build();
这仍然并行生成项目,这可能是缓慢的部分。
https://stackoverflow.com/questions/72580753
复制相似问题