隐藏并行流ParallelStream中隐藏的陷阱( 二 )
Lambda/Stream其实并不是天然线程安全的 , 线程安全的前提是它们本身被线程封闭调用 , 并且不引入多线程环境 , 像使用了并行流 , 本质就是引入了多线程环境 。 所以 , 在开发功能的时候 , 需要仔细思考一下:
- 是否真的有必要使用Lambda和流式编程?
- 是否真的有必要用到并行流?如果使用了并行流 , 是否需要考虑引入额外的同步机制 , 例如锁?
- 如果引入了额外的同步机制 , 是否考虑是强行使用并行流 , 违反了并行流设计的初衷?
- 其实并发并不能提高性能 , 只能提高吞吐量 , 应该着重去发现和优化性能瓶颈 , 而不是拼命地把上游改造成并发调用 。
笔者有代码洁癖 , 当时还发现了上面的代码存在映射操作 , 正确来说应该使用map()函数 , 而不是forEach()去遍历元素重新装进去另一个列表 , 方法中的逻辑体现了原开发者其实对Lambda一知半解 。
?
小结 回到最初那个问题 , 其实使用并行流也可以保证执行结果和预期一致 , 不过一定需要引入额外的同步机制 , 例如这里使用「监视器」进行同步:
public class ParallelStreamMain { public static void main(String[] args) throws Exception { List<List> array = new ArrayList<>() List item1 = new ArrayList<>() List item2 = new ArrayList<>() List target = new ArrayList<>(100) array.add(item1) array.add(item2) final Object monitor = new Object() array.parallelStream().forEach(x -> { synchronized (monitor) { for (int i = 0 i < 100000 i++) { target.add(i) } } }) System.out.println(target.size()) }} 上面的方法无论执行多少次 , 最终都只会输出:200000 。 这里在并行流中添加同步代码块的逻辑看起来确实比较滑稽 , 仅仅是为了说明如果在多线程环境下 , 对一个容器进行元素增加或者修改 , 只有添加额外的同步机制 , 才能保证最终的结果是符合预期的 。 ParallelStream是一个十分优秀的设计 , 但是需要考量其适用的场景 , 避免踏进自己为自己埋下的并发陷阱 。
【隐藏并行流ParallelStream中隐藏的陷阱】
推荐阅读
- 界面新闻除了看得见的,奔驰EQC背后还隐藏着这些“看不见”的豪华
- 大妈聊事|强推《弱点》:从捡垃圾到世界冠军,那些隐藏在最隐秘角落的人性
- 翻转|金字塔内一串神秘的数字:142857,隐藏了地球向高能跃迁的秘密!
- 游戏八达通|炉石传说:安德罗妮再用喵咪隐藏玩法,狂战才是T0,其他都是渣
- 热血传奇|热血传奇:血饮的这个隐藏属性,直接让它成为法师的热爱!(二)
- 中国海军|这一刻足足等了70年,终于不再隐藏实力,俄:没想到中国如此强大
- 廖凡|廖凡隐藏9年的老婆,比他大5岁不说,还是我们的老熟人!
- 海警|中国居然还有“第二海军”?隐藏实力多年,战力究竟有多强?
- 产业气象站 你没发现这些微信隐藏彩蛋,简直是宝藏,除了拍一拍
- 手机除了拍一拍,你没发现这些微信隐藏彩蛋,简直是宝藏
