It seems that when using ordered Streams to process a short-circuiting operation on a difficult to bound numeric range, parallel()
cannot be used.
E.g.:
public class InfiniteTest {
private static boolean isPrime(int x) {
if (x < 2) {
return false;
}
if (x % 2 == 0 && x > 2) {
return false;
}
// loop while i <= sqrt(x), using multiply for speedup
for (int i = 3; i * i <= x; i += 2) {
if (x % i == 0) {
return false;
}
}
return true;
}
private static int findNthPrime(final int n) {
// must not use infinite stream, causes OOME
// but even big size causes huge slowdown
IntStream.range(1, 1000_000_000)
// .parallel()
.filter(InfiniteTest::isPrime)
.skip(n - 1)
.findFirst()
.getAsInt();
}
public static void main(String[] args) {
int n = 1000; // find the nth prime number
System.out.println(findNthPrime(n));
}
}
This sequential stream works fine. But when I add parallel()
, it seems to run forever (or very long at last). I assume it's because the stream threads work on arbitrary numbers instead of starting with the first numbers in the stream. I cannot usefully bound the range of integers to scan for prime numbers.
So is there any simple trick to run this problem in parallel with streams without that trap, such as forcing the splititerator to serve chunks of work from the beginning of the stream? Or building the stream from substreams that cover increasing number ranges? Or somehow setting up the multithreading as producer/consumer pattern but with streams?
Similar questions all just seem to try to discourage use of parallel: