Multi-threaded operation List

In multi-threaded operation List scenarios, generally the List object is too large and needs to be split. Or the same attribute value needs to be taken in multiple lists. Each processing time is relatively long, at this time, multithreading can be used to speed up the processing efficiency. If it is in a non-transactional operation scenario, each thread can be directly processed separately and finally aggregated. If it is a transactional operation scenario, set the transaction to submit manually before the database operation, and then use submit to submit the task, and the Feature will obtain the execution result of each thread. If successful, the transaction is committed at one time, and the transaction is rolled back if it fails.

The following is a template code, multiple threads to calculate the value of the list. You can refer to this template to adapt to other business scenarios. its main logic

1. Use SplitListUtils to split the list

2. Use CountDownLatch to block the main thread and wait for the execution results of multiple tasks

3. The thread pool uses submit to execute tasks and obtain the results of each task. You can also use invokeAll() here.

4. Process each result for calculation.

/**
 * 多线程处理List
 */
@Slf4j
public class ThreadList {
    public static void main(String[] args) throws InterruptedException {

        AtomicInteger atomicIntegerAll = new AtomicInteger(0);
        List<Child> childList = generChildList(10000);

        List<List<Child>> split = SplitListUtils.split(childList, 1000);//拆分10个子list
        ExecutorService executorService = new ThreadPoolExecutor(10,10,100,TimeUnit.SECONDS,new ArrayBlockingQueue<Runnable>(1));
        CountDownLatch countDownLatch = new CountDownLatch(10);
        List<Future<Integer>> futureList = new ArrayList<>();

        for (List<Child> children:split){
                Future<Integer> submit  = executorService.submit(()-> {
                AtomicInteger sum = new AtomicInteger(0);
                for (int i = 0;i<children.size();i++){
                  sum.getAndAdd(children.get(i).getNum());
                }
                log.info("计数{}", sum.get());
                return sum.get();
            });
            futureList.add(submit);
            countDownLatch.countDown();
        }
        countDownLatch.await();
        futureList.forEach(integerFuture -> {
            try {
                atomicIntegerAll.getAndAdd(integerFuture.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        });
        log.info("计数{}", atomicIntegerAll.get());
        executorService.shutdown();

    }

    /**
     * 生成LIST
     * @param num
     * @return
     */
    public static List<Child> generChildList(int num){
        List<Child> childList = new ArrayList<>();
        for (int i =0 ; i <num ; i++){
            Child child = new Child();
            child.setNum(i);
            childList.add(child);
        }
        return childList;
    }

Tools 

/**
 * 拆分结合工具类
 */
public class SplitListUtils {
    /**
     * 拆分集合
     *
     * @param <T> 泛型对象
     * @param resList 需要拆分的集合
     * @param subListLength 每个子集合的元素个数
     * @return 返回拆分后的各个集合组成的列表
     * 代码里面用到了guava和common的结合工具类
     **/
    public static <T> List<List<T>> split(List<T> resList, int subListLength) {
        if (CollectionUtils.isEmpty(resList) || subListLength <= 0) {
            return new ArrayList();
        }
        List<List<T>> ret = new ArrayList();
        int size = resList.size();
        if (size <= subListLength) {
            // 数据量不足 subListLength 指定的大小
            ret.add(resList);
        } else {
            int pre = size / subListLength;
            int last = size % subListLength;
            // 前面pre个集合,每个大小都是 subListLength 个元素
            for (int i = 0; i < pre; i++) {
                List<T> itemList = new ArrayList();
                for (int j = 0; j < subListLength; j++) {
                    itemList.add(resList.get(i * subListLength + j));
                }
                ret.add(itemList);
            }
            // last的进行处理
            if (last > 0) {
                List<T> itemList = new ArrayList();
                for (int i = 0; i < last; i++) {
                    itemList.add(resList.get(pre * subListLength + i));
                }
                ret.add(itemList);
            }
        }
        return ret;
    }
}

Guess you like

Origin blog.csdn.net/weixin_42740540/article/details/125804171