Java并行流注意,Java并行流:如何等待线程完成并行流?

So I have a list from which I obtain a parallel stream to fill out a map, as follows:

Map map = new HashMap<>();

List list = some_filled_list;

//Putting data from the list into the map

list.parallelStream().forEach(d -> {

TreeNode node = new TreeNode(d);

map.put(node.getId(), node);

});

//print out map

map.entrySet().stream().forEach(entry -> {

System.out.println("Processing node with ID = " + entry.getValue().getId());

});

The problem with this code is that the map is being printed out when the "putting data" process is still going on (cuz it's parallel), so as a result, map has not yet received all the elements from the list yet. Of course, in my real code, it is not just printing out the map; I use a map to take advantage of O(1) lookup time.

My question is:

how to make the main thread wait so that the "putting data" is finished before the map is printed out? I tried to put the "putting data" inside a thread t, and do t.start() and t.join(), but that doesn't help.

Maybe I am not supposed to use parallel stream in this case? The list is long, and I just want to take advantage of the parallelism to improve efficiency.

解决方案

With this list.parallelStream().forEach you are violating the side-effects property that is explicitly stated in the Stream documentation.

Also when you say this code is that the map is being printed out when the "putting data" process is still going on (cuz it's parallel), this is not true, as forEach is a terminal operation and it will wait to be finished, until it can go an process the next line. You might be seeing that as such, since you are collecting to a non thread-safe HashMap and some entries might not be in that map... Think about about other way, what would happen if you would put multiple entries from multiple threads in a HashMap? Well, lots of things can break, like missing entries, on incorrect/inconsistent Map, etc.

Of course, changing that to a ConcurrentHashMap would work, since it's thread-safe, but you are still violating the side-effect property, although in a "safe" way.

The correct thing to do is to collect to a Map directly without forEach:

Map map = list.parallelStream()

.collect(Collectors.toMap(

NodeData::getId,

TreeNode::new

));

This way, even for parallel processing, everything would be fine. Just notice that you would need lots (tens of thousands elements) to have any measurable performance increase from parallel processing.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值