# [obsolete] Fibonacci function: An example of how to write concurrent programs without multi-threading

Posted by rexyoung on March 18, 2012 at 2:14 PM PDT

[Update on 4/25/2012: The source code listed here are out of date. The latest version is 1.3.74, and its use is much clear and simpler.]

The post describes three implementations of the Fibonacci function. Each implementation demonstrates a different programming model: sequential, multi-thread and active-object programming.

By definition, each number in the Fibonacci sequence is the sum of the previous two numbers, starting with 0 and 1.

``F(n) = F(n-1) + F(n-2)``

The definition formula does not fit the goal of the post which wants to see what different programming model looks like in a concurrent program. I use another well-known formula mentioned here at http://www.cs.utexas.edu/users/EWD/ewd06xx/EWD654.PDF.

``F(2j)   = F(j)^2 + F(j+1)^2F(2j+1) = [2 * F(j) + F(j+1)] * F(j+1)``

This formula will lead to a recursive program in which each recursive step needs to do two things. For a F(n) you need find out the known F(n/2) and F(n/2 + 1), then use them to compute F(n) and F(n+1) according to the formula above. The post is not demonstrating the Fork/Join framework form JDK 7 so I will keep the recursive part the same and apply three different programming models to the computation part. The computation has three multiplications and additions. When N is a large number say over 1,000,000 multiplications will takes significant CPU time. That is why I want to parallelize this part. On the other hand additions are insignificant, there will be no special handling for them.

Let’s move to something real. You can download two jar files from http://java.net/projects/fastmessenger/downloads. One contains the Fast Messenger framework and the other contains test programs. Both jars have source codes in it. You can run a test program using one of commands below.

``java -classpath jar1:jar2 com.fastmessenger.example.fibonacci.serial.SerialMainjava -classpath jar1:jar2 com.fastmessenger.example.fibonacci.thread.ThreadMainjava -classpath jar1:jar2 com.fastmessenger.example.fibonacci.messenger.MessengerMain``

Figure 1: Common structure of test programs

Figure 1 illustrates the common structure of test programs. The Main class prepares a Formula implementation and pass it to Recursion class which performs the same recursive steps for all implementations of computation. Formula implementation classes are the places we should look into because they show how different programming models perform the same computation.

``public class SerialFormula implements Formula {    public BigInteger[] compute (BigInteger Fj, BigInteger Fj1) {        BigInteger Fn = Fj.multiply (Fj).add (Fj1.multiply (Fj1));        BigInteger Fn1 = Fj.add (Fj).add (Fj1).multiply (Fj1);        return new BigInteger[] { Fn, Fn1 };    }}``

This is the sequential version. It is very straightforward. Let’s take a look at multi-thread version below. Please refer to a full version of source code in the jar file.

``public class ThreadFormula implements Formula {    protected ExecutorService executor;    public BigInteger[] compute (BigInteger Fj, BigInteger Fj1) {        Future Fjxj = executor.submit (new ThreadMultiplyTask (Fj, Fj));        Future Fj1xj1 = executor.submit (new ThreadMultiplyTask (Fj1, Fj1));        BigInteger Fi = Fj.add (Fj).add (Fj1);        Future Fixj1 = executor.submit (new ThreadMultiplyTask (Fi, Fj1));        BigInteger Fn = Fjxj.get ().add (Fj1xj1.get ());        BigInteger Fn1 = Fixj1.get ();        return new BigInteger[] { Fn, Fn1 };    }}public class ThreadMultiplyTask implements Callable {    protected BigInteger a, b;    public BigInteger call () {        return a.multiply (b);    }}``

ThreadFormula class submits all multiplications to a thread pool, namely an instance of ExecutorService, and receives Future instances respectively. Then it calls the Future.get() methods that forces it to wait for results. This way each of three multiplications will be computed by a separate thread from the thread pool.

Figure 2: Structure of messaging between the host and workers.

The active object version as Figure 2 illustrate is similar to the multi-thread version in terms of mindset. They both send a request for multiplication to another entity either thread or active object. Then the main thread waits until it receives multiplication results from those threads and active objects.

Since Fast Messenger is a new project to everyone, the post is not going to push it too hard. I am ending it here after listing some source code. If you are interested in knowing details, please leave feedback here or at project’s forum at http://java.net/projects/fastmessenger/forums. Feedbacks will be addressed by follow up posts. Thank you.

``public class MessengerFormula implements Formula, Receiver {    public static final String MESSAGE_PORT = "multiply-done";    protected Node node;    protected MessageAddress myAddress;    protected List workerAddressesList;    protected Object callerVsCallerLock = new Object ();    protected Object callerVsWorkerLock = new Object ();    public MessengerFormula (Node node, MessageAddress hostAddress, List workerAddressList) {        this.node = node;        this.myAddress = hostAddress;        this.workerAddressesList = workerAddressList;    }    // work varibles per call    protected int workerCount;    protected LinkedList workers;    protected LinkedList tasks;    protected BigInteger Fj, Fjxj, Fj1, Fj1xj1, Fi, Fixj1;    public BigInteger[] compute (BigInteger fj, BigInteger fj1) {        synchronized (callerVsCallerLock) {            synchronized (callerVsWorkerLock) {                Fj = fj;                Fj1 = fj1;                Fi = Fj.add (Fj).add (Fj1);                workerCount = workerAddressesList.size ();                workers = new LinkedList (workerAddressesList);                tasks = new LinkedList ();                tasks.add (new MessengerMultipleMessage (1, Fj, Fj));                tasks.add (new MessengerMultipleMessage (2, Fj1, Fj1));                tasks.add (new MessengerMultipleMessage (3, Fi, Fj1));                sendMessageToIdleWorkers ();                try {                    callerVsWorkerLock.wait ();                } catch (InterruptedException e) {                    throw new RuntimeException (e);                }                BigInteger Fn = Fjxj.add (Fj1xj1);                BigInteger Fn1 = Fixj1;                workers = null;                tasks = null;                Fj = Fjxj = Fj1 = Fj1xj1 = Fi = Fixj1 = null;                return new BigInteger[] { Fn, Fn1 };            }        }    }    protected void sendMessageToIdleWorkers () {        while (workers.size () > 0 && tasks.size () > 0) {            MessageAddress workerAddress = workers.poll ();            MessengerMultipleMessage msg = tasks.poll ();            msg.setHostAddress (myAddress);            msg.setWorkerAddress (workerAddress);            node.sendMessage (msg, workerAddress.getActiveObjectId (), workerAddress.getMessagePort ());        }    }    public void onMessage (Object message, String receiverPort) {        if (!MESSAGE_PORT.equals (receiverPort) || !(message instanceof MessengerMultipleMessage)) {            return;        }        MessengerMultipleMessage msg = (MessengerMultipleMessage) message;        synchronized (callerVsWorkerLock) {            if (msg.getId () == 1) {                Fjxj = msg.getMultiple ();            } else if (msg.getId () == 2) {                Fj1xj1 = msg.getMultiple ();            } else if (msg.getId () == 3) {                Fixj1 = msg.getMultiple ();            }            workers.add (msg.getWorkerAddress ());            if (tasks.size () == 0 && workers.size () == workerCount) {                callerVsWorkerLock.notify ();            } else {                sendMessageToIdleWorkers ();            }        }    }}public class MessengerMultipleWorker implements Receiver {    public static final String MESSAGE_PORT = "to-multiply";    protected Node node;    public void onMessage (Object message, String receiverPort) {        if (!MESSAGE_PORT.equals (receiverPort) || !(message instanceof MessengerMultipleMessage)) {            return;        }        MessengerMultipleMessage msg = (MessengerMultipleMessage) message;        msg.setMultiple (msg.getA ().multiply (msg.getB ()));        node.sendMessage (msg, msg.getHostAddress ().getActiveObjectId (), msg.getHostAddress ().getMessagePort ());    }}``
AttachmentSize
fibonacci-full-structure.png65.47 KB
fibonacci-messaging-structure.png62.97 KB
Related Topics >>