Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/380.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Java中,使用多线程向列表中添加一些信息最有效的方法是什么?_Java_Multithreading_List_Concurrency - Fatal编程技术网

在Java中,使用多线程向列表中添加一些信息最有效的方法是什么?

在Java中,使用多线程向列表中添加一些信息最有效的方法是什么?,java,multithreading,list,concurrency,Java,Multithreading,List,Concurrency,我有一些任务,使用多线程技术,以最有效的方式从多个链接聚合一些信息。链接位于某个数组中。现在,我有了类似于此的解决方案: Arrays.stream(link).parallel().forEach(link -> { try { String result = doSomeJobWithLink(link); System.out.println(result); } catch (IOException e

我有一些任务,使用多线程技术,以最有效的方式从多个链接聚合一些信息。链接位于某个数组中。现在,我有了类似于此的解决方案:

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);
List resultList=Collections.synchronizedList(new ArrayList());
Arrays.stream(link).parallel().forEach(link->{
试一试{
字符串结果=doSomeJobWithLink(链接);
结果列表。添加(结果);
}捕获(IOE异常){
e、 printStackTrace();
}
});
resultList.forEach(System.out::println);
但这需要5-8秒而不是2秒。我能不能加快速度?

使用以下代码:

List<String> resultList = Arrays.stream(link).parallel().map(v -> doSomeJobWithLink(v)).collect(Collectors.toList());
List resultList=Arrays.stream(link.parallel().map(v->doSomeJobWithLink(v)).collect(Collectors.toList());
通常我们避免在流管道中尝试捕获,但若必须捕获异常,请阅读

不要仅仅因为可以而使用
parallel
,因为额外的开销会比没有
parallel

请参见使用以下代码:

List<String> resultList = Arrays.stream(link).parallel().map(v -> doSomeJobWithLink(v)).collect(Collectors.toList());
List resultList=Arrays.stream(link.parallel().map(v->doSomeJobWithLink(v)).collect(Collectors.toList());
通常我们避免在流管道中尝试捕获,但若必须捕获异常,请阅读

不要仅仅因为可以而使用
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());
List resultList=Arrays.stream(link.parallel().map(e->{
字符串结果=null;
试一试{
结果=doSomeJobWithLink(e);
}捕获(IOEX异常){
例如printStackTrace();
返回null;
}
返回结果;
}).filter(e->e!=null).collect(collector.toList());

不确定下面的代码是否能提高性能,但我认为这将是一种更干净的方法来解决您的问题

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());
List resultList=Arrays.stream(link.parallel().map(e->{
字符串结果=null;
试一试{
结果=doSomeJobWithLink(e);
}捕获(IOEX异常){
例如printStackTrace();
返回null;
}
返回结果;
}).filter(e->e!=null).collect(collector.toList());

当您这样做时,
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 resultList=Arrays.stream(link.parallel().map(e->{
试一试{
返回doSomeJobWithLink(e);
}捕获(IOEX异常){
例如printStackTrace();
返回null;
}
返回结果;
}).filter(Objects::nonNull).collect(collector.toList());

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

当您这样做时,
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 resultList=Arrays.stream(link.parallel().map(e->{
试一试{
返回doSomeJobWithLink(e);
}捕获(IOEX异常){
例如printStackTrace();
返回null;
}
返回结果;
}).filter(Objects::nonNull).collect(collector.toList());

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

尝试将结果列表的初始容量设置为输入数组的大小。是的,现在是2秒,尝试将结果列表的初始容量设置为输入数组的大小。是的,现在是2秒,THX返回null始终是实现NPE的第一步。不要那样做。抛出自定义异常或返回空列表。返回null始终是NPE的第一步。不要那样做。抛出自定义异常或返回空列表