diff --git a/src/main/java/lambdasinaction/chap7/ForkJoinHarness.java b/src/main/java/lambdasinaction/chap7/ForkJoinHarness.java new file mode 100644 index 00000000..1fa22391 --- /dev/null +++ b/src/main/java/lambdasinaction/chap7/ForkJoinHarness.java @@ -0,0 +1,11 @@ +package lambdasinaction.chap7; + +/** + * This harness demonstrates difference between recursive implementation vs usage of fork/join (for divide-conquer algorithms) + */ +public class ForkJoinHarness { + public static void main(String[] args) { + System.out.println("ForkJoin sum done in: " + ParallelStreamsHarness.measurePerf(ForkJoinSumStatelessCalculator::forkJoinSum, 1_000_000_000L) + " msecs" ); + System.out.println("Recursive sum done in: " + ParallelStreamsHarness.measurePerf(ForkJoinSumStatelessCalculator::recursiveSum, 1_000_000_000L) + " msecs" ); + } +} diff --git a/src/main/java/lambdasinaction/chap7/ForkJoinSumStatelessCalculator.java b/src/main/java/lambdasinaction/chap7/ForkJoinSumStatelessCalculator.java new file mode 100644 index 00000000..e91389bc --- /dev/null +++ b/src/main/java/lambdasinaction/chap7/ForkJoinSumStatelessCalculator.java @@ -0,0 +1,72 @@ +package lambdasinaction.chap7; + +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.RecursiveTask; + +import static lambdasinaction.chap7.ParallelStreamsHarness.FORK_JOIN_POOL; + +public class ForkJoinSumStatelessCalculator extends RecursiveTask { + + public static final long THRESHOLD = 10_000; + + private final int start; + private final int end; + + public ForkJoinSumStatelessCalculator(int n) { + this(0, n); + } + + private ForkJoinSumStatelessCalculator(int start, int end) { + this.start = start; + this.end = end; + } + + @Override + protected Long compute() { + int length = end - start; + if (length <= THRESHOLD) { + return computeSequentially(); + } + ForkJoinSumStatelessCalculator leftTask = new ForkJoinSumStatelessCalculator(start, start + length/2); + leftTask.fork(); + ForkJoinSumStatelessCalculator rightTask = new ForkJoinSumStatelessCalculator(start + length/2, end); + Long rightResult = rightTask.compute(); + Long leftResult = leftTask.join(); + return leftResult + rightResult; + } + + private long computeSequentially() { + long sum = 0; + for (int i = start; i < end; i++) { + sum += i; + } + return sum; + } + + private static long computeSequentially(int start, int end) { + long sum = 0; + for (int i = start; i < end; i++) { + sum += i; + } + return sum; + } + + public static long computeRecursively(int start, int end) { + int length = end - start; + if (length <= THRESHOLD) { + return computeSequentially(start, end); + } + long leftSum = computeRecursively(start, start + length/2); + long rightSum = computeRecursively(start + length / 2, end); + return leftSum + rightSum; + } + + public static long forkJoinSum(long n) { + ForkJoinTask task = new ForkJoinSumStatelessCalculator((int) n); + return FORK_JOIN_POOL.invoke(task); + } + + public static long recursiveSum(long n) { + return computeRecursively(0, (int) n); + } +} \ No newline at end of file