[ Java ] 线程池问题疑惑,大佬们赐教

2019-09-12 09:28:23 +08:00
 aibccn

背景:在 controller 里并发调用三个其他服务接口,然后组装数据返回

@RequestMapping({"/flow/test"})
@ResponseBody
public String hello(HttpServletRequest request, @RequestParam(name = "tabId", required = false) Integer tabId) {


    ExecutorService servicepool = Executors.newFixedThreadPool(10);

    ExecutorCompletionService<String> service = new ExecutorCompletionService<String>(servicepool);

    service.submit(() -> {
        String uri = "http://localhost/api/user/info";
        return HttpHelper.getRequest(uri, 300);

    });

    service.submit(() -> {

        String uri = "http://localhost/api/news/list";
        return HttpHelper.getRequest(uri, 300);

    });
    service.submit(() -> {

        String uri = "http://localhost/api/flow/list";
        return HttpHelper.getRequest(uri, 300);

    });
    List<String> curlResult = new ArrayList<>();
    try {
        servicepool.shutdown();
        for (int i = 0; i < 3; i++) {
            curlResult.add(service.take().get());
        }

    } catch (Exception ex) {

    }
    //TODO 组装数据

    return JSON.toJSON(curlResult).toString();
}

问题:这样写可不可以?有什么弊端或者是有什么需要注意的地方,请大佬们指点一二

6941 次点击
所在节点    Java
30 条回复
wysnylc
2019-09-12 17:11:00 +08:00
@chocotan #10 +2
changhe626
2019-09-12 17:17:07 +08:00
10 +3
notreami
2019-09-12 17:50:21 +08:00
@NoString 如果 HttpHelper.getRequest(uri, 300);多个的处理时间相同,在 add 的时候获取地址一样,那么肯定列表只留一个。
可以具体说明下嘛?我理解 parallelStream 是有线程安全问题,但是不存在并行结果合并的情况吧。
lazyfighter
2019-09-12 18:26:56 +08:00
你这写的啥啊,我艹,真的一点思考没有啊 ,拼程序啊
guyeu
2019-09-12 18:52:48 +08:00
如果稍微有点要求的话:
1. 数据和业务拆分;
2. 公共线程池+异步调用返回 Future ;
3. 对响应做缓存 /复用;
NoString
2019-09-12 18:53:56 +08:00
@notreami #23 这块是我表述的有问题,怪我没说明情况。丢失的情况是开启并行管道后 list 引发的安全问题,而本身的 forkjiontask 的处理其实不存在问题,是并行添加合并了。比如 foreach 里执行的合并操作,你这个应该没事 毕竟.collect(Collectors.toList()) 是执行一批合一批 我的我的 呜呜呜 你这个已经解决他的问题了,除了只能用公共线程池之外都挺好 点赞点赞
guyeu
2019-09-12 18:55:43 +08:00
@NoString #19
@NoString #20
即使处理时间相同,在 add 的时候获取地址一样,那么列表是一个有三个相同元素的列表,parallelStream 的问题仅仅是并发导致不保证顺序,并不会帮你合并相同的任务。
NoString
2019-09-12 19:23:35 +08:00
@guyeu #27 emmm 我说的意思是这个 list1.parallelStream().forEach(oa -> list2.add(oa)); 若是 2 楼带哥的 collect(Collectors.toList()) 顺序都是稳的
NoString
2019-09-12 19:24:01 +08:00
@guyeu #27 呜呜呜 说的离谱了 我的我的
notreami
2019-09-12 19:49:15 +08:00
@NoString 吓我一跳,查了半天资料,一点头绪都没有,幸好你回复了。哈哈

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://tanronggui.xyz/t/600260

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX