As I mentioned, I am looking at Programming Concurrency on the JVM by Venkat Subramaniam. I got to an example that used the java.util.concurrent.Callable interface. I then went out looking for some more examples. I have put what I have done up on Github. I used a class by Lars Vogella in my code, and then I looked at a few other examples to see the pattern, and made a couple of my own.
Java had an interface called java.lang.Runnable from the beginning. One issue with it is that it does not return a value. I am not going to look at that too much or all of the methods of java.lang.Thread. The general consensus is that the world should move beyond the old ways.
This post is pretty big with the code, so I will put the code in this post and talk about it tomorrow.
Here is a class that implements the java.util.concurrent.Callable interface.
package info.shelfunit.concurrency.callable; import java.util.List; import java.util.LinkedList; import java.util.UUID; import java.util.concurrent.Callable; import info.shelfunit.util.ShelfLogger; import org.apache.log4j.Logger; public class CallableWorker implements Callable< Double > { private final int num; private final String idString; private static Logger logger; public CallableWorker(int num, String idString) { logger = ShelfLogger.getInstance().getLogger(); this.num = num; this.idString = idString; logger.info("Starting CallableWorker " + num + ", " + idString); } @Override public Double call() throws Exception { logger.info("Starting CallableWorker.call in " + num + ", " + idString); this.hello(); double sum = 0; Thread.sleep( num * 1000 ); for ( double i = 0; i <= 100; i++ ) { sum += ( i * num ); } Thread.sleep( num * 1000 ); logger.info("Ending CallableWorker.call in " + num + ", " + idString); return sum; } // end method call private void hello() { logger.info("in CallableWorker.hello in " + num + ", " + idString); } } // end class info.shelfunit.concurrency.callable.CallableWorker
Here is a class that calls the class we just made.
package info.shelfunit.concurrency.callable; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import info.shelfunit.util.ShelfLogger; import org.apache.log4j.Logger; public class ForwardCallableRunner { private static final int NTHREDS = 10; private static int iterations; private static ShelfLogger shelfLogger; private static Logger logger; public static void setIterations() { try { iterations = new Integer( System.getProperty( "iterations" ) ); } catch ( Exception e) { e.printStackTrace(); iterations = 5; // some default value } } public static void main( String[] args ) throws InterruptedException { logger = ShelfLogger.getInstance().getLogger(); setIterations(); String idString; ExecutorService executor = Executors.newFixedThreadPool( NTHREDS ); List< Future< Double > > futureList = new ArrayList< Future< Double > >(); for ( int i = 0; i <= iterations; i++ ) { idString = UUID.randomUUID().toString(); logger.info( "Starting a new CallableWorker: " + i + ", " + idString ); Callable< Double > worker = new CallableWorker(i, idString); Thread.sleep( 2 * 1000 ); logger.info( "About to submit CallableWorker: " + i + ", " + idString ); Future< Double > submit = executor.submit( worker ); logger.info( "About to add to futureList CallableWorker: " + i + ", " + idString ); logger.info( " ------ " ); futureList.add( submit ); } long sum = 0; logger.info( "The size of the list is: " + futureList.size() ); for ( Future< Double > future : futureList ) { try { sum += future.get(); } catch ( InterruptedException e ) { e.printStackTrace(); } catch ( ExecutionException e ) { e.printStackTrace(); } } // for ( Future< Double > future : futureList ) logger.info( "The sum is: " + sum ); executor.shutdown(); } // end method main } // ForwardCallableRunner
I will go through the code in a couple of days.
Image from the Rheinau Psalter, a 13th century manuscript housed at Central Library of Zurich. Image from e-Codices. This image is assumed to be allowed under Fair Use.