Exceptional behavior of parallel stream
Tagir F. Valeev
amaembo at gmail.com
Thu Aug 18 11:58:46 UTC 2016
Hello, Doug!
Thank you for your response.
DL> In your example, you can witness the delayed termination of other threads
DL> upon exception in another because you add side-effecting operations
DL> (here, just printing). Avoiding all this would force sequential processing.
DL> But if the supplied functions follow the documented properties,
DL> it should not matter that parallel processing of some elements continues
DL> when another hits an exception. Which is why nothing is said about it.
DL> Similar effects occur in findAny and other methods. I don't see any benefit
DL> in trying to specify exactly what happens in these cases.
Note that functions supplied to peek, forEach and forEachOrdered
methods, according to the documentation are allowed to produce
side-effect (otherwise these operations would be completely useless).
Thus my example does not violate the documented way of using streams.
While you may argue that the "peek" is intended for debugging use,
it's still possible to show the same effect using forEach. Thus I
don't agree that using Streams in documented way you cannot hit this
problem. Of course using forEach is usually discouraged, but it's
still legal API method.
With best regards,
Tagir Valeev.
DL> -Doug
>>
>> String[] data = IntStream.range(0, 100).mapToObj(String::valueOf)
>> .toArray(String[]::new);
>> data[20] = "oops";
>> try {
>> int sum = Arrays.stream(data).parallel().mapToInt(Integer::valueOf)
>> .peek(System.out::println).sum();
>> System.out.println("Sum is "+sum);
>> } catch (NumberFormatException e) {
>> System.out.println("Non-number appeared!");
>> }
>>
>> This parses integers stored in string array and sums them outputting
>> every number to stdout once it processed. As data set contains
>> non-number, the stream obviously fails with NumberFormatException. The
>> typical output looks like this:
>>
>> 62
>> 63
>> 12
>> 31
>> 87
>> ...
>> 28
>> 92
>> 29
>> 8
>> Non-number appeared!
>> 9
>> 30
>>
>> So as you can see, the stream is not actually terminated when
>> exception is thrown and caught: even after that some parallel tasks
>> continue running, and you see more numbers printed after catch block
>> is executed.
>>
>> I consider such behavior as confusing and unexpected. Given the fact
>> that stream may produce side-effects (e.g. if terminal op is forEach)
>> this might lead to unforeseen consequences in user programs as
>> left-over parallel stream tasks may continue mutate shared state after
>> main stream thread exceptionally returns the control to the caller.
>>
>> So I suggest that such behavior should be either fixed or explicitly
>> documented. What do you think?
>>
>> With best regards,
>> Tagir Valeev.
>>
>>
More information about the core-libs-dev
mailing list