首頁  >  問答  >  主體

Java8Stream异常处理

我也是刚用上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);

我用了这种方法确实停下来了,那还有什么好的方法,或者说是否有何问题,这样的话就拿不到具体哪个线程有问题了吧

PHPzPHPz2744 天前725

全部回覆(2)我來回復

  • 高洛峰

    高洛峰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估計能滿足你的要求。

    回覆
    0
  • PHPz

    PHPz2017-04-18 10:50:40

    CountDownLatch(1)

    catch異常時:

    CountDownLatch.countDown();

    最後:

    CountDownLatch.await();
    xxx.stop();
    

    Java8的Stream沒用過了。 。 。

    回覆
    0
  • 取消回覆