并发编程系列---【数组切割并行查询-解决sql的in超过1000的问题】

1.问题

List<List<Object>> splitList = CollUtil.split(dataList, 800);
List<User> resultList =new ArrayList<>();
// 使用parallelStream输出切割后的结果,每个子列表的大小
splitList.parallelStream().forEach(sublist -> {
   List<User> users = userMapper.selectByIds(sublist);
   resultList.addAll(users);
});

上面这段代码中,resultList是一个ArrayList,而ArrayList是非线程安全的。在并行流的操作中,多个线程可能会同时调用addAll方法,这可能导致竞态条件,可能导致数据丢失或抛出ConcurrentModificationException,解决方案有下面三种,推荐第三种。

2.解决方案

  1. 使用线程安全的集合
    使用Collections.synchronizedList来包装你的ArrayList

    List<User> resultList = Collections.synchronizedList(new ArrayList<>());
    
    splitList.parallelStream().forEach(sublist -> {
        List<User> users = userMapper.selectByIds(sublist);
        resultList.addAll(users);
    });
    
  2. 使用并发集合
    使用CopyOnWriteArrayList或其他适合的并发集合。

    List<User> resultList = new CopyOnWriteArrayList<>();
    
    splitList.parallelStream().forEach(sublist -> {
        List<User> users = userMapper.selectByIds(sublist);
        resultList.addAll(users);
    });
    
  3. 使用collect操作
    使用流的collect方法来收集结果,这样可以避免手动处理并发问题。

    List<User> resultList = splitList.parallelStream()
        .flatMap(sublist -> userMapper.selectByIds(sublist).stream())
        .collect(Collectors.toList());
    

第三种方法通常是推荐的,因为它更符合流的使用范式,并且处理好了并发问题。

posted on   少年攻城狮  阅读(15)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
历史上的今天:
2019-12-06 开发中遇到的问题---【feign的多参数问题】
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示