package fj.demo.concurrent; import static fj.Bottom.error; import fj.F; import fj.P; import fj.P2; import fj.Unit; import fj.data.List; import fj.control.parallel.Actor; import fj.control.parallel.Promise; import fj.control.parallel.Strategy; import fj.function.Effect1; import static fj.data.List.range; import static fj.function.Integers.add; import static fj.control.parallel.Promise.join; import static fj.control.parallel.Promise.promise; import static fj.control.parallel.Actor.actor; import java.text.MessageFormat; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Parallel Fibonacci numbers. * Based on a Haskell example by Don Stewart. * Author: Runar */ public class Fibs {private static final int CUTOFF = 35; public static void main(final String[] args) {if (args.length < 1) throw error("This program takes an argument: number_of_threads"); final int threads = Integer.parseInt(args[0]); final ExecutorService pool = Executors.newFixedThreadPool(threads); final Strategy<Unit> su = Strategy.executorStrategy(pool); final Strategy<Promise<Integer>> spi = Strategy.executorStrategy(pool); // This actor performs output and detects the termination condition. final Actor<List<Integer>> out = actor(su, new Effect1<List<Integer>>() {public void f(final List<Integer> fs) {for (final P2<Integer, Integer> p : fs.zipIndex()) {System.out.println(MessageFormat.format("n={0} => {1}", p._2(), p._1()));} pool.shutdown();}}); // A parallel recursive Fibonacci function final F<Integer, Promise<Integer>> fib = new F<Integer, Promise<Integer>>() {public Promise<Integer> f(final Integer n) {return n < CUTOFF ? promise(su, P.p(seqFib(n))) : f(n - 1).bind(f(n - 2), add);}}; System.out.println("Calculating Fibonacci sequence in parallel..."); join(su, spi.parMap(fib, range(0, 46)).map(Promise.sequence(su))).to(out);} // The sequential version of the recursive Fibonacci function public static int seqFib(final int n) {return n < 2 ? n : seqFib(n - 1) + seqFib(n - 2);}}