You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lombok @Singular注解如何实现线程安全的Builder?

Lombok @Builder 搭配@Singular的线程安全实现方案

Lombok 原生没有提供直接的配置开关,可一键生成支持线程安全的@Singular Builder。默认实现下@Singular注解为List类型字段生成的Builder存储容器是普通ArrayList,多线程并发调用单元素添加方法时,确实会出现元素缺失、状态不一致、数组下标越界等并发问题。

以下是两种低冗余的可行实现方案,不需要完全放弃@Singular注解手写全量Builder逻辑:

  • 方案1:覆写Builder内的集合初始化逻辑,保留全部@Singular原生能力
    你只需要在实体类中写对应Builder静态内部类,手动定义对应集合字段为线程安全容器即可,Lombok检测到该字段已存在时,不会重复生成字段定义,其余单元素添加、批量添加、build()、clear()等方法仍会由@Singular自动生成,所有操作都会作用在你定义的线程安全容器上,样板代码量极低:

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import lombok.Builder;
    import lombok.Singular;
    
    @Builder
    public class Avengers {
        @Singular
        private List<String> members;
    
        // 仅手动定义集合字段,其余Builder逻辑由Lombok自动生成
        public static class AvengersBuilder {
            private List<String> members = Collections.synchronizedList(new ArrayList<>());
        }
    }
    

    如果是Set、Map类型的@Singular字段,对应替换为Collections.synchronizedSet()、Collections.synchronizedMap()包装的线程安全容器即可。

  • 方案2:并发场景下先独立收集元素,再一次性传入Builder
    如果不方便修改实体类的Builder定义,可以避免多线程直接操作同一个Builder实例,先在线程任务中把元素添加到线程安全的收集容器中,等待所有任务执行完成后,调用@Singular生成的批量添加方法一次性传入所有元素:

    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.TimeUnit;
    
    // 初始化线程安全的收集容器
    final List<String> memberCollector = Collections.synchronizedList(new ArrayList<>());
    ExecutorService executorService = Executors.newFixedThreadPool(3);
    executorService.submit(() -> memberCollector.add("Iron Man"));
    executorService.submit(() -> memberCollector.add("Thor"));
    executorService.submit(() -> memberCollector.add("Captain America"));
    // 等待所有任务执行完成
    executorService.shutdown();
    executorService.awaitTermination(1, TimeUnit.MINUTES);
    
    // 一次性传入所有元素构建实例
    final Avengers team = Avengers.builder()
            .members(memberCollector)
            .build();
    

    该方案完全不需要调整实体类的Lombok配置,线程安全逻辑收敛在业务组装侧,适配无法修改实体类定义的场景。

两种方案都可以保留@Singular的核心特性:build()生成的最终集合是不可变的、支持单元素/批量添加语义、支持Builder状态重置,相比全手写Builder可以减少90%以上的冗余样板代码。

内容的提问来源于stack exchange,提问作者Krease

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 16:01:03