【问题标题】:NullPointerException when switch from stream to parallelStream从流切换到并行流时出现 NullPointerException
【发布时间】:2018-01-24 08:25:57
【问题描述】:

帮助我理解这一点;我有一个基于流的逻辑,它根据由其字段构造的一些键字符串将实体分组到列表映射中。

使用流运行没有任何错误:

Map<String, List<Entity>> mapOfkeyToListOfEntities = baseJournalEntries
.stream()
.collect(Collectors.groupingBy(eneity -> buildKey(entity)));

但如果我尝试通过将 steam() 方法更改为 parallelStream() 来并行执行此操作,如下所示:

Map<String, List<Entity>> mapOfkeyToListOfEntities = baseJournalEntries
.parallelStream()
.collect(Collectors.groupingBy(entity -> buildKey(entity)));

我得到一个例外:

Caused by: java.lang.NullPointerException
     at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
     at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
     at sun.reflect.DelegatingConstructorAccessorImpl.__newInstance(DelegatingConstructorAccessorImpl.java:45)
     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java)
     at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java)
     at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
     at java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:598)
     at java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:677)
     at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:735)
     at java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:714)
     at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
     at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)

由于流版本有效,所有实体都能够生成密钥,因此 buildKey 中不能有 NPE...我不明白。我需要看哪里?

【问题讨论】:

  • 我猜buildKey() 中存在并发错误。请提供minimal reproducible example
  • enEity -> buildKey(entity)
  • 您发布的堆栈跟踪表示在调用者线程中重新创建异常。此异常应该有另一个原因,原始异常的堆栈跟踪将显示原始异常发生的位置。
  • 可能修复也可能不修复。如果没有 buildKey 的来源和它调用的函数,这是不可能的答案。你能给出包含 buildKey 的类的来源吗?
  • 为什么不知道buildKey 做了什么以及为什么会失败。将其设为synchronized 可确保不会同时调用它,但如果假设它以特定顺序与流元素一起调用,它仍然可能会失败。

标签: java parallel-processing nullpointerexception java-stream


【解决方案1】:

buildKey 方法中确实发生了 NullPointerException,但该异常被 ForkJoin 框架吞没了,或者看起来是这样。它在初始堆栈跟踪中完全不可见;只有通过在 buildKey 中捕获运行时异常并打印它,我才能使其可见。 (NPE本身确实是代码运行在不同的线程上造成的,没有绑定一些线程相关的数据。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-19
    • 2018-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    相关资源
    最近更新 更多