Let's discuss how people try to use the Fork Join pool in Java 7. Imagine that you have a class that extends RecursiveTask.
@Override
protected BigInteger compute() {
if ((n - start) >= THRESHOLD) {
Collection<FactorialTask> tasks = ForkJoinTask
.invokeAll(getSubTasks());
BigInteger result = BigInteger.ONE;
for (FactorialTask t : tasks) {
result = t.join().multiply(result);
}
return result;
} else {
return calculate(start, n);
}
}
Ok, and do you know how some people try to transfer this code into the java 8 style? Yep, that's the code that you may find when you surf the web:
@Override
protected BigInteger compute() {
if ((n - start) >= THRESHOLD) {
return ForkJoinTask
.invokeAll(createSubtasks())
.stream()
.map(ForkJoinTask::join)
.reduce(BigInteger.ONE, BigInteger::multiply);
} else {
return calculate(start, n);
}
}
Off-course they still have additional methods:
private BigInteger calculate(int start, int finish) {
return IntStream.rangeClosed(start, finish)
.mapToObj(BigInteger::valueOf)
.reduce(BigInteger.ONE, BigInteger::multiply);
}
private Collection<FactorialTask> getSubTasks() {
List<FactorialTask> tasks = new ArrayList<>();
int mid = (start + n) / 2;
tasks.add(new FactorialTask(start, mid));
tasks.add(new FactorialTask(mid + 1, n));
return tasks;
}
In order to invoke:
public BigInteger factorial(Integer number){ ForkJoinPool pool = ForkJoinPool.commonPool(); return pool.invoke(new FactorialTask(number)); }
BUT wait! In Java 8+ we have a parallel stream, why don't rewrite this code in one line? Everything is just simple:
IntStream.rangeClosed(1, number) .parallel() .mapToObj(BigInteger::valueOf) .reduce(BigInteger::multiply);
Sometimes the solution is quite simple.
No comments:
Post a Comment