0
点赞
收藏
分享

微信扫一扫

多线程处理有序集合



文章目录

  • 前言
  • 一、多线程处理有序集合?
  • 总结


前言

通过多线程,处理数据是一个快速提高处理的手段,那么当用多线程处理的时候,如果遇到有序集合怎么办?例如: 我想爬取一本小说,那么爬取完成后,需要的是 一个有序的章节小说,而非混乱的 章节,如何做呢?

一、多线程处理有序集合?

例如前言中说的,就是处理有序集合,但是一般情况下,多线程处理数据都是无序的,现在模拟这个场景,例如我要计算1-100的和,但是记住要有序!!

废话不多说,直接上代码:

public class 多线程处理顺序集合 {


    @SneakyThrows
    public static void main(String[] args) {

        List<Future<Integer>> resultList = new ArrayList<>();

        ExecutorService service = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            Future<Integer> submit = service.submit(new MyCallAbale(i));
            resultList.add(submit);
        }

        service.shutdown();

        Integer res = 0;
        for (Future<Integer> integerFuture : resultList) {
            Integer integer = integerFuture.get();
            System.out.println(integer);
            res += integer;
        }

        System.out.println(res);

    }

    static class MyCallAbale implements Callable<Integer> {

        private Integer num;

        public MyCallAbale(Integer num) {
            this.num = num;
        }

        @Override
        public Integer call() throws Exception {
            Integer res = 0;
            for (Integer i = num * 10+1; i <= (num + 1) * 10; i++) {
                res += i;
            }
            return res;
        }
    }
}

多线程处理有序集合_数据

  • 我们利用线程池处理Executors
  • 处理有序集合,切记做好拆分,就是每个线程处理的是一段数据,这样这段数据内部顺序即使是乱的也无所谓,因为我要做的是整体有序就好
  • submit 中的 Callable 接口可以返回结果,利用此来得到每个线程的计算结果
  • service.shutdown(); 停止当前线程,但是不会立即停止,而是等待所有任务都执行完毕才会停止;这样就保证了所有线程执行完毕
  • 利用 Future 的get() 方法获取每个线程的执行结果,得到最终计算结果
  • 可以看到,打印的顺序就是有序的,每段的和也是对的,这就是有序集合的多线程处理

总结

Executors 线程池虽好用,但是不建议直接使用,可以通过全局线程池配置,然后每次使用一个配置,否则各处单独使用线程池,很乱,其次当有问题后,也不好排查;
用完 Executors 记住一定要 service.shutdown(); 或者类似方法, 否则线程池一直存在,不结束;

这里其实我省略了对于list集合的拆分,或者隐形进行了拆分,其实具体拆分逻辑可以参考这篇文章:
传送门大概思路

  1. 根据已有数据,可以每个线程需要处理的数据量,进行计算
  • 取余 为0 说明刚刚好分配完,那么线程数就是 总数/分配数 的商智
  • 取余 不为0 说明 有多余一点的数据,那么总线程数 就是 总数/分配数 的 商值 +1
  1. 这样,总线程 数就确定了,然后开始分割集合,就是循环将符合每个线程的数据,分配给这个线程即可
  2. 然后根据分配好的任务,线程池执行就行了,与上文基本一致了


举报

相关推荐

0 条评论