繁体   English   中英

如何最有效地将一些信息添加到 Java 中的多线程列表中?

[英]How most effective add some info to list with multiple threads in Java?

我有一些任务使用多线程以最有效的方式从多个链接聚合一些信息。 链接位于某个数组中。 到目前为止,我有这样的解决方案:

Arrays.stream(link).parallel().forEach(link -> {
        try {
            String result = doSomeJobWithLink(link);
            System.out.println(result);
        } catch (IOException e) {
            e.printStackTrace();
        }
    });

它工作得很好(工作已经完成了 2 秒)。

但是我不想在我的 try 块中打印结果,而是在某个列表(或其他集合)中收集结果,所以我这样做了:

List<String> resultList = Collections.synchronizedList(new ArrayList<>());
Arrays.stream(link).parallel().forEach(link -> {
        try {
            String result = doSomeJobWithLink(link);
            resultList.add(result);
        } catch (IOException e) {
            e.printStackTrace();
        }
    });
resultList.forEach(System.out::println);

但它花了大约 5-8 秒而不是两秒。 我可以以某种方式加快速度吗?

当你这样做时, Collections.synchronizedList(new ArrayList<>()) ,你把一个synchronized放在整个列表上,即列表上的任何操作共享相同的互斥锁,甚至读取,这会降低性能,并且是限制因素。

更好的方法是只收集到普通列表, 收集器保证无序并发减少。

对于并发收集器,实现可以自由地(但不要求)同时实现减少。 并发减少是指从多个线程并发调用累加器函数,使用相同的可并发修改的结果容器,而不是在累加期间保持结果隔离。 仅当收集器具有 Collector.Characteristics.UNORDERED 特征或原始数据无序时,才应应用并发减少。

所以下面应该显着提高性能,

List<String> resultList = Arrays.stream(link).parallel().map(e -> {
            try {
                return doSomeJobWithLink(e);
            } catch (IOException ex) {
                ex.printStackTrace();
                return null;
            }
            return result;
        }).filter(Objects::nonNull).collect(Collectors.toList());

尽管不建议吞下异常,除非这是不可避免的。

使用以下代码:

List<String> resultList = Arrays.stream(link).parallel().map(v -> doSomeJobWithLink(v)).collect(Collectors.toList());

通常我们避免在流管道中尝试捕获,但如果您必须捕获异常,请阅读Java Streams 中的异常处理

并且不要仅仅因为你可以使用parallel ,因为额外的开销你的工作将比没有parallel需要更多的时间

请参阅我应该尽可能使用并行流吗?

不确定下面的代码是否会提高任何性能,但我认为这将是解决您问题的更简洁的方法。

List<String> resultList = Arrays.stream(link).parallel().map(e -> {
            String result = null;
            try {
                result = doSomeJobWithLink(e);
            } catch (IOException ex) {
                ex.printStackTrace();
                return null;
            }
            return result;
        }).filter(e -> e != null).collect(Collectors.toList());

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM