Future使用问题记录

问题描述

记录下一次代码评审的问题点,发现这个也是自己以前犯过的内容.在使用多线程情况下,查看日志发现似乎还是单线程在跑的效果

问题案例

先看下面的代码

@Slf4j
public class ThreadPoolTest2 {

    private static ThreadPoolExecutor testThreadPool = new ThreadPoolExecutor(10, 10, 180L,
            TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), new CustomizableThreadFactory("test-pool-"), new ThreadPoolExecutor.CallerRunsPolicy());


    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        handlerA();
        log.info("耗时->{}ms", System.currentTimeMillis() - startTime);
    }

    private static void handlerA() {

        for (int i = 0; i < 100; i++) {
            String param = i + "";
            Future<String> resultFuture = testThreadPool.submit(() -> getResult(param));
            String result = null;
            try {
                result = resultFuture.get();
            } catch (Exception e) {
                e.printStackTrace();
            }
            log.info("handlerA future get,result->{}", result);
        }
    }

    private static String getResult(String i) {
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        String result = "result-" + i;
        log.info("result->{}", result);
        return result;
    }

}

查看日志,可以看到是有不同的线程在跑任务,但效果就是单线程的效果.耗时也是单线程情况下的耗时


image.png

问题分析以及解决方案

先看下下面修改后的代码,对比下

private static void handlerB() {
       List<Future<String>> futureList = new ArrayList<>();

       for (int i = 0; i < 30; i++) {
           String param = i + "";
           Future<String> resultFuture = testThreadPool.submit(() -> getResult(param));
           futureList.add(resultFuture);
       }

       for (Future<String> resultFuture : futureList) {
           String result = null;
           try {
               result = resultFuture.get();
           } catch (Exception e) {
               e.printStackTrace();
           }
           log.info("handlerB future get,result->{}", result);
       }
   }

先看下效果(可以看到这个才是自己想要的多线程的效果)


image.png

原因分析

其实对比下代码,可以发现,在main线程遍历过程中使用future.get().这个急阻塞main线程等到线程完成任务.这样其实就和单线程是同样的效果了
在优化后的handlerB中,main线程优先使用线程跑任务,最终才使用main从future列表里等待线程任务结束.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容