多线程并行处理:线程池、Callable、Future


前言:通过Rpc调上游接口,上游接口限制入参ids的个数(3个)并且调一次耗时大约1000毫秒,现在假如ids数量是10个,应该如何操作效率高耗时短

方案:循环单个处理、分组串行、分组并行

1. 上游接口

    /**
     * 上游接口:ids最多限制3个
     *
     * @param ids
     * @return
     */
    public static Set<String> getIdsStr(Set<String> ids) {
        //业务逻辑、Rpc上游接口
       Set<String> idSet = Sets.newHashSet();
        try {
            Thread.sleep(1000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        for (String str : ids) {
            String res = str + "-----" + str;
            idSet.add(res);
            System.out.println(Thread.currentThread().getName() + ":" +res);
        }

        System.out.println("通过id拼接的idStr:"+Thread.currentThread().getName() + ":" +idSet);
        return idSet;
    }

2. 方案

2.1. 循环单个处理

      public static void main(String[] args) {
        long start = System.currentTimeMillis();

        Set<String> ids = new HashSet<>();
        ids.add("1");
        ids.add("2");
        ids.add("3");
        ids.add("4");
        ids.add("5");
        ids.add("6");
        ids.add("7");
        ids.add("8");
        ids.add("9");
        ids.add("10");

        Set<String> resultSet = new HashSet<>(ids.size());
        List<String> idList = new ArrayList<>();
        idList.addAll(ids);
        for (int i = 0; i < ids.size(); i++) {
            Set<String> id = new HashSet<>();
            id.add(idList.get(i));
            resultSet.addAll(getIdsStr(id));
        }
        System.out.println(resultSet);
        long end = System.currentTimeMillis();
        long l = end - start;
        System.out.println("总耗时:" + l);
    }

在这里插入图片描述

2.2. 分组串行

    /**
     * 按数量进行切割
     *
     * @param ids
     * @param limit
     * @return
     */
    public static Map<String, Set<String>> splitSet(Set<String> ids, int limit) {
        Map<String, Set<String>> map = Maps.newHashMap();
        if (CollectionUtil.isEmpty(ids)) {
            return map;
        }
        List<String> skuList = Lists.newArrayList(ids);
        int i = 0;
        while (skuList.size() > limit) {
            List<String> subList = skuList.subList(0, limit);
            map.put(String.valueOf(i), Sets.newHashSet(subList));
            i++;
            skuList.removeAll(subList);
        }
        if (CollectionUtil.isNotEmpty(skuList)) {
            map.put(i + "", Sets.newHashSet(skuList));
        }
        return map;
    }
    public static void main(String[] args) {
        long start = System.currentTimeMillis();

        Set<String> ids = new HashSet<>();
        ids.add("1");
        ids.add("2");
        ids.add("3");
        ids.add("4");
        ids.add("5");
        ids.add("6");
        ids.add("7");
        ids.add("8");
        ids.add("9");
        ids.add("10");

        Set<String> resultSet = new HashSet<>(ids.size());
        ExecutorService threadPool =
            new ThreadPoolExecutor(10, 100, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(4),
                new ThreadPoolExecutor.AbortPolicy());
        Map<String, Set<String>> batchIdMap = splitSet(ids, 3);
        for (String batch : batchIdMap.keySet()) {
            Future<Set<String>> submit = threadPool.submit(() -> getIdsStr(batchIdMap.get(batch)));
            try {
                //future的get方法会阻塞:串行执行
                Set<String> idSet = submit.get(5000L, TimeUnit.MILLISECONDS);
                resultSet.addAll(idSet);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        System.out.println(resultSet);
        long end = System.currentTimeMillis();
        long l = end - start;
        System.out.println("总耗时:" + l);
    }

在这里插入图片描述

2.3. 分组并行

    /**
     * 按数量进行切割
     *
     * @param ids
     * @param limit
     * @return
     */
    public static Map<String, Set<String>> splitSet(Set<String> ids, int limit) {
        Map<String, Set<String>> map = Maps.newHashMap();
        if (CollectionUtil.isEmpty(ids)) {
            return map;
        }
        List<String> skuList = Lists.newArrayList(ids);
        int i = 0;
        while (skuList.size() > limit) {
            List<String> subList = skuList.subList(0, limit);
            map.put(String.valueOf(i), Sets.newHashSet(subList));
            i++;
            skuList.removeAll(subList);
        }
        if (CollectionUtil.isNotEmpty(skuList)) {
            map.put(i + "", Sets.newHashSet(skuList));
        }
        return map;
    }
      public static void main(String[] args) {
        long start = System.currentTimeMillis();

        Set<String> ids = new HashSet<>();
        ids.add("1");
        ids.add("2");
        ids.add("3");
        ids.add("4");
        ids.add("5");
        ids.add("6");
        ids.add("7");
        ids.add("8");
        ids.add("9");
        ids.add("10");

        Set<String> resultSet = new HashSet<>(ids.size());
        ExecutorService threadPool =
            new ThreadPoolExecutor(10, 100, 1, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(4),
                new ThreadPoolExecutor.AbortPolicy());
        Map<String, Set<String>> batchIdMap = splitSet(ids, 3);
        Map<String, Future<Set<String>>> futureMap = Maps.newHashMap();

        for (String batch : batchIdMap.keySet()) {
            Future<Set<String>> submit = threadPool.submit(() -> getIdsStr(batchIdMap.get(batch)));
            futureMap.put(batch,submit);
        }
        for (String batch : futureMap.keySet()){
            try {
                resultSet.addAll(futureMap.get(batch).get(5000L, TimeUnit.MILLISECONDS));
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        System.out.println(resultSet);
        long end = System.currentTimeMillis();
        long l = end - start;
        System.out.println("总耗时:" + l);
    }

在这里插入图片描述

3、总结

从以上的耗时可以看出效率由高到低的是:分组并行、分组串行、循环单个处理

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值