简体   繁体   English

执行并行时出现异常 Stream Java 8

[英]Getting an exception while executing parallel Stream Java 8

I am writing a function that calculates the sum of squares of digit for a given number.我正在编写一个 function 来计算给定数字的数字平方和。 I am calling this function for a number from 1 to 1000 in parallel.我将这个 function 并行调用为从 1 到 1000 的数字。 But I am getting an exception some time.但我有时会遇到一个例外。

public static void main(String[] args) throws Exception {
    IntStream stream = IntStream.rangeClosed(1, 1000);
    Map < Integer, Integer > numbers = new TreeMap < > ();
    stream.parallel().forEach(i - > {
        int result = digitSquareSum(i);
        numbers.put(i, result);
    });
    Files.write(Paths.get("result.csv"), () - > numbers.entrySet().stream()
        . < CharSequence > map(e - > e.getKey() + "," + e.getValue())
        .iterator());
}

private static int digitSquareSum(int i) {
    int result = 0;
    int temp = 0;
    while (i != 0) {
        temp = i % 10;
        result = result + temp * temp;
        i = i / 10;
    }
    return result;
}

I am getting following exception我收到以下异常

Exception in thread "main" java.lang.NullPointerException
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:488)
    at java.base/java.util.concurrent.ForkJoinTask.getThrowableException(ForkJoinTask.java:590)
    at java.base/java.util.concurrent.ForkJoinTask.reportException(ForkJoinTask.java:668)
    at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:726)
    at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:160)
    at java.base/java.util.stream.ForEachOps$ForEachOp$OfInt.evaluateParallel(ForEachOps.java:189)
    at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
    at java.base/java.util.stream.IntPipeline.forEach(IntPipeline.java:417)
    at java.base/java.util.stream.IntPipeline$Head.forEach(IntPipeline.java:574)

My aim is to write an efficient method that calculates sum of squares of digit of the number and writes it to the csv file in ascending order manner.我的目标是编写一个有效的方法来计算数字的平方和并将其以升序方式写入 csv 文件。

As mentioned in the comments, you are getting this exception, because TreeMap is not thread safe.正如评论中提到的,你得到了这个异常,因为TreeMap不是线程安全的。 From javadoc :javadoc

Note that this implementation is not synchronized.请注意,此实现不同步。 If multiple threads access a map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally.如果多个线程同时访问map,并且至少有一个线程在结构上修改了map,则必须对外同步。 (A structural modification is any operation that adds or deletes one or more mappings; merely changing the value associated with an existing key is not a structural modification.) (结构修改是添加或删除一个或多个映射的任何操作;仅更改与现有键关联的值不是结构修改。)

I beleive you are using TreeMap to preserve the order of your initial numbers.我相信您正在使用TreeMap来保留初始数字的顺序。 But it's not necessary (and also introduces side-effects ): you could use Collectors.toList() which collects all the input elements into a List, in encounter order .但这不是必需的(并且还引入了副作用):您可以使用Collectors.toList()所有输入元素按遇到顺序收集到一个列表中

This will also allow you to avoid creation of the second stream to write these numbers to a file:这也将允许您避免创建第二个 stream 将这些数字写入文件:

List<String> lines = IntStream.rangeClosed(1, 1000)
            .parallel()
            .mapToObj(i -> i + " -> " + digitSquareSum(i))
            .collect(Collectors.toList());
Files.write(Paths.get("result.csv", lines); // the lines will come in the right order

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM