简体   繁体   中英

Lombok @Singular - how to make it threadsafe?

This is a question about Lombok's @Builder and @Singular annotations and thread safety

As a simplified example, consider this class:

@Builder
public class Avengers {
    @Singular
    private List<String> members;
}

This generates a builder, where I can do this:

final Avengers team = Avengers.builder()
    .member("Iron Man")
    .member("Thor")
    .member("Captain America")
    .build();
System.out.println(team.getMembers());  // ["Iron Man", "Thor", "Captain America"]

Now for the problem - what I want to do is something like this (again, this is oversimplified to make the point):

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();

Why is this a problem?

The generated builder is not threadsafe (Lombok backs it by an ArrayList ), so the result of team.getMembers() may be incomplete or in an inconsistent state due to this.

Question: Is there a way to have Lombok generate a threadsafe builder that lets me use this "Singular" pattern?

My workaround thus far has been to avoid Singular and create my own threadsafe builder methods, but I'm hoping to eliminate this boilerplate.

It's not possible. Anyway, trying to share a builder across multiple threads is highly unusual. You'd do much better to store all the results, then iterate them and add them all to the builder on the same thread.

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();

This still parallelizes the generation of the items, which is presumably the slow part.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM