我正在编写一个程序,并决定使用新的Streams API for Java 8.但是,当我介绍.parallel()
时,我的程序停止了工作。这是相关的代码:
import java.math.BigInteger;
import java.util.Objects;
import java.util.stream.Stream;
import com.google.common.cache.*;
public class Alg196 {
public static void main(String[] args) {
// Add .parallel() where suitable
long c = Stream
.iterate(BigInteger.valueOf(101), i -> i.add(BigInteger.ONE))
.limit(100000000).map(BigInteger::toString).map(Alg196::alg196)
.filter(Objects::nonNull).count();
System.err.println(c);
}
private static final String reverse(String n) {
return new StringBuilder(n).reverse().toString();
}
private static final boolean isPalindrome(String s) {
for (int i = 0, j = s.length() - 1; i < j; ++i, --j) {
if (s.charAt(i) != s.charAt(j))
return false;
}
return true;
}
private static final String alg196(String n) {
System.err.println("PROCESSING " + n);
int loops = 0;
while (!isPalindrome(n)) {
n = new BigInteger(n).add(new BigInteger(reverse(n))).toString();
loops++;
if (loops >= 100) {
return null;
}
}
if (loops <= 10) {
return null;
}
return n;
}
}
正常工作时,输出将包含许多PROCESSING <x>
行,但.parallel()
不会发生这种情况。这是为什么?
答案 0 :(得分:2)
你的程序没有停止 - 在向执行程序提交map任务之前尝试生成请求的BigIntegers范围(在你的情况下是100000000)很努力(尝试将断点放在BigInteger :: add()方法 - 而你我会看到的。
从线程转储中也很容易看到
"ForkJoinPool.commonPool-worker-2@710" daemon prio=5 tid=0xe nid=NA runnable java.lang.Thread.State: RUNNABLE
at java.util.stream.Stream$1.next(Stream.java:1033)
at java.util.Spliterators$IteratorSpliterator.trySplit(Spliterators.java:1784)
at java.util.stream.AbstractShortCircuitTask.compute(AbstractShortCircuitTask.java:114)
at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731)
at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289)
at java.util.concurrent.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:902)
at java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1689)
at java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1644)
at java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:157)`
另外请注意将许多长时间运行的任务提交到公共ForkJoin池,因为您可能会阻塞池中的所有线程 - 您可以检查此线程(Custom thread pool in Java 8 parallel stream)以获取解决方案
答案 1 :(得分:0)
事实证明limit
是一个短路操作,这意味着它会在运行任何其他内容之前生成所有100,000,000
BigIntegers
。毕竟不是死锁!