获取list中的数据使用多线程执行入库

1.将list分割并用多线程处理

private SyncRespData dealListByPool(List<Map<String,Object>> list, int nThreads, String uniqueCode) throws Exception {
        if (list == null || list.isEmpty()) {
            throw new NullPointerException("the collection is null");
        }

        //计算每个分组存多个数据

        int capactiy = list.size() % nThreads > 0 ? list.size() / nThreads : list.size() / nThreads + 1;
        if(list.size()<16){
            capactiy=1;
        }
        //进行数据分组(分任务)例如,对包含[a,b,c,d,e]的列表进行分区,分区大小为3,得到[[a,b,c],[d,e]]——一个包含三个和两个元素的两个内部列表的外部列表,所有列表都按原始顺序排列。
        List<List<Map<String,Object>>> partions = Lists.partition(list, capactiy);
        // 创建一个临时的局部线程池(固定大小)
        ExecutorService executorService = Executors.newFixedThreadPool(nThreads);
        // 保存结果
        List<Future<SyncRespData>> futures = new ArrayList<Future<SyncRespData>>(partions.size());

        // 分配任务
        for (int i = 0; i < partions.size(); i++) {
            // 小任务
            SyncToMatrixCallable callTask = new SyncToMatrixCallable(partions.get(i),uniqueCode);
            //同步执行多个小任务
            futures.add(executorService.submit(callTask));
        }
        // 关闭线程池
        executorService.shutdown();
        // 合并
        List<Map<String,Object>> result = new ArrayList<Map<String,Object>>();
        int ignoreCount=0;
        int insertCount=0;
        int updateCount=0;
       
        for (Future<SyncRespData> future : futures) {
            try {
                // 合并
                SyncRespData syncRespData = future.get();
                result.addAll(syncRespData.getData());
                ignoreCount = ignoreCount + syncRespData.getIgnoreCount();
                insertCount = insertCount + syncRespData.getInsertCount();
                updateCount = updateCount + syncRespData.getUpdateCount();
                log.info("不同线程插入总数据条数:{}",JSON.toJSONString(syncRespData));
            } catch (Exception e) {
                log.info("执行定时任务异常:{}",e.getMessage());
                throw new Exception("执行定时任务异常:"+JSON.toJSONString(e.getMessage()),e);
            }
        }
        log.info("主线程结束");
        SyncRespData build = SyncRespData.builder().data(result).ignoreCount(ignoreCount).insertCount(insertCount).updateCount(updateCount).build();
        
        return build;
    }

2.多线程实际执行的类

private class SyncToMatrixCallable implements Callable<SyncRespData> {

        private final List<Map<String,Object>> list;


        private final String uniqueCode;

        private final ReentrantLock lock = new ReentrantLock();

        private SyncToMatrixCallable(List<Map<String, Object>> list, String uniqueCode) {
            this.list = list;

            this.uniqueCode = uniqueCode;
        }

        @Override
        public SyncRespData call() throws Exception {
            // 标记子线程开始
            log.info(Thread.currentThread().getName() + " Callable 子线程开始...");
            //结果存储
            List<Map<String,Object>> resultList = new ArrayList<>();

            int ignoreCount = 0;
            int insertCount = 0;
            int updateCount = 0;

            // 业务逻辑处理
            for (Map<String, Object> objectMap : list) {
                lock.lock();
                
                try {
                    List<Map<String, Object>> save = save(data);
                    resultList.addAll(save);
                }catch (Exception e){
                    throw new Exception("数据处理失败:"+JSON.toJSONString(e.getMessage()),e);
                }finally {
                    lock.unlock();
                }
            }

            // 标记子线程结束
            log.info(Thread.currentThread().getName() + " Callable 子线程结束...");
            
            return SyncRespData.builder().data(resultList).ignoreCount(ignoreCount).insertCount(insertCount).updateCount(updateCount).build();
        }
    }

调用多线程代码

SyncRespData syncRespData = dealListByPool(list, 16, uniqueCode);

以上就是对已获取到的list数据量很大时,先分割大小然后使用多线程入库,由于list中可能存在相同的数据,这时需要达到第一条数据新增,第二条数据更新的效果,使用了ReentrantLock,保证的数据的一致性。

如果不使用ReentrantLock保证数据一致性,还可以使用CopyOnWriteArrayList,使用方法如下:

final CopyOnWriteArrayList<Map<String, Object>> list = new CopyOnWriteArrayList<>(data);

SyncRespData syncRespData = dealListByPool(list, 16, transferObject, fieldMap, rule, uniqueCode);

对比上述两种保证多线程数据一致性的方法,使用ReentrantLock的效率稍微高点。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,使用多线程的方式执行list集合数据,可以在Runnable对象实现具体的任务逻辑,并通过线程池来管理多个线程的执行。以下是一个示例代码: ```java import java.util.ArrayList; import java.util.List; import java.util.concurrent.*; public class ThreadPoolExample { public static void main(String[] args) { // 创建一个包含5个线程的线程池 ExecutorService executor = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); // 创建一个包含10个元素的List集合 List<Integer> list = new ArrayList<>(); for (int i = 1; i <= 10; i++) { list.add(i); } // 执行任务 for (Integer element : list) { executor.execute(new MyRunnable(element)); } // 关闭线程池 executor.shutdown(); } static class MyRunnable implements Runnable { private Integer element; public MyRunnable(Integer element) { this.element = element; } @Override public void run() { System.out.println("正在处理元素:" + element); } } } ``` 在这个示例,我们定义了一个MyRunnable类,实现了Runnable接口,并在run()方法实现了具体的任务逻辑。然后,我们使用for-each循环遍历List集合的每个元素,并创建一个MyRunnable对象,并将其提交给线程池去执行。在MyRunnable的构造函数,我们将List集合的元素作为参数传入,并保存在成员变量,在run()方法使用。最后,我们关闭了线程池,等待所有任务都完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iamlzjoco

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值