我也是刚用上Java8的Stream,所有的一切都还在照猫画虎的阶段。
在异常处理这块不敢贸然前进,因为我看到某篇文的这样一段话
在单线程环境中,使用捕获受检异常并重新抛出非受检异常的方法是可行的。但是在多线程环境这样用,就存在一些风险。
多线程环境中,Lambda表达式中发生的错误会被自动传递到主线程中。这会带来两个问题:
这不会停止其他正在并行执行的Lambda表达式。 如果有多个线程抛出了异常,在主线程中却只能捕获到一个线程中的异常。如果这些异常信息都很重要的话,那么更好的方法是在Lambda表达式中就进行异常处理并将异常信息作为结果的一部分返回到主线程中。
我现在是用的Stream流的Map方法,当然用的是并发,想在map里的方法里只要有一个出错就让他停下来,不运行其他的。。这个需求该怎么搞。。
paths.stream()
.map(path -> {
try {
return new File(path).getCanonicalPath();
} catch(IOException ex) {
throw new RuntimeException(ex);
}
})
.forEach(System.out::println);
我用了这种方法确实停下来了,那还有什么好的方法,或者说是否有何问题,这样的话就拿不到具体哪个线程有问题了吧
高洛峰2017-04-18 10:50:40
你的思维模式就不对,map filter 这类不是语法糖, java8还是有函数式编程能力的。
函数式的核心是不变性,这里不是要求取消变量,而是要建立一种等价思维,以求值 > 过程的方式去思考问题。
你的例子,比如要求在map中停下来这就在设计之外,因为map的语意保证了它一定会遍历完所有数据,返回的类型一定一致,而且长度相同。同样贸然抛出rumtime exception也是非常的不优雅。
有几个方案,
使用optional或者either(这个官方不提供,需要自己弄一个)来包装你的返回类型来保证map语义(把错误放到返回值里去,但是类型不变,具体可以百度)
如果你的数据有前后关系,使用fold(reduce)来处理而不是map。
不使用stream而用回for break,编程其实就是编程,关键是解决问题,针对问题来选择最好的方案,有的时候steam方案不如传统的for,fork/join也不如手工sync notify。
另,stream的并行其实没有你想的那么好,滥用了copyonwrite,我自己玩过一阵之后几乎再也不用了。
不过 java8有个completableFuture估计能满足你的要求。
PHPz2017-04-18 10:50:40
CountDownLatch(1)
catch异常时:
CountDownLatch.countDown();
最后:
CountDownLatch.await();
xxx.stop();
Java8的Stream没用过了。。。