parallelStream如何处理异常?

时间:2018-11-22 09:58:35

标签: java parallel-processing

我正在用Java处理并行流。我的代码非常简单,一张地图包含两个键。我想为每个键并行调用一个函数。 现在,其中一项关键功能引发了异常。

我不明白为什么第二个键没有执行功能。

map.put(1,1);     
map.put(2,2);
map.entrySet().parallelStream()
                    .map(batch -> function(batch.getKey()))
                    .collect(Collectors.toList());


f(key)
      if(key==1) throw new Exception();
      System.out.print("printing: "key)

2 个答案:

答案 0 :(得分:1)

如果您的Stream仅包含两个元素,则流框架可能不会创建两个线程来处理这两个元素。因此,一旦第一个元素引发异常,第二个元素将不会被处理。

实际上,当我尝试与您的代码相似的代码时,但没有例外,我发现这2个元素实际上是在main线程上处理的:

public static int function(int key) {
    System.out.print("printing: " + key + " " + Thread.currentThread ().getName () + " ");
    return key;
}

public static void main (java.lang.String[] args)
{
    HashMap<Integer,Integer> map = new HashMap<>();
    for (int i = 1 ; i <= 2 ; i ++) {
        map.put(i,i);     
    }

    map.entrySet().parallelStream()
                  .map(batch -> function(batch.getKey()))
                  .collect(Collectors.toList());
}

此输出:

printing: 1 main printing: 2 main

仅当Stream较大时,工作才会拆分为多个线程,因此为一个元素引发的异常不会影响其余元素的处理。

如果将Stream的大小增加到5,我得到:

printing: 1 ForkJoinPool.commonPool-worker-1 printing: 2 ForkJoinPool.commonPool-worker-1 printing: 3 ForkJoinPool.commonPool-worker-1 printing: 4 main printing: 5 main

所以现在将工作分为两个线程。

如果我在第一个元素上抛出RuntimeException,我将得到:

printing: 4 main printing: 5 main Exception in thread "main" java.lang.RuntimeException

如您所见,分配给引发异常的线程的元素未被处理,但是分配给另一个线程的元素被处理。

答案 1 :(得分:0)

使用parallelStream时

  • 启动一个大小为1的处理器的后台线程池,如果尚未运行,则需要一些时间。从计算机的角度来看,很长一段时间。
  • 它将任务添加到工作队列。
  • 当前线程加入了执行这些任务的线程池。

注意:主线程可以在后台池启动之前很长时间完成所有操作。

简而言之,将工作传递给后台线程不是瞬时的,特别是如果它们尚未运行。

这是一个运行中的流程在新流程开始之前可以完成的大部分工作的示例。

static volatile int counter = 0;

static void countTo(int n) {
    for (int i = 0; i < n; i++)
        counter = i;
}

public static void main(String[] args) {
    countTo(10_000_000);
    counter = 0;
    new Thread(() -> System.out.println("counter=" + A.counter)).start();
    countTo(10_000_000);
}

在我的机器上打印类似

counter=21017