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.