Search This Blog

Thursday, 31 October 2013

And They All Work Together

In the previous post we had a look at the invokeAny method that allowed us to get the result from the first thread to complete. ExecutorService also provides us with the invokeAll method that will execute all the tasks given. Consider the below code:

public class InvokeAllEg {
  private static Random random = new Random((long)Math.random() * 3);
 
  private static int getProblemInput() {
          int nxtNo = random.nextInt();
          nxtNo = nxtNo < 0 ? nxtNo * -1 : nxtNo;
          return nxtNo/1000; //just reducing the size of number
  }
 
  public static void main(String[] args) throws InterruptedException,
                  ExecutionException {
          final int PARTICIPANT_COUNT = 5;
          Collection<Participant> participants = new ArrayList<Participant>(PARTICIPANT_COUNT);
         
          for (int i = 0; i < PARTICIPANT_COUNT; i++) {
                  Participant participant = new Participant(getProblemInput());
                  participants.add(participant);
          }
          System.out.println("Start solving ..");
          ExecutorService executorService = Executors.newFixedThreadPool(PARTICIPANT_COUNT);
          try {
                  List<Future<Long>> solutionParts = executorService.invokeAll(participants);
                  long result = 0;
                  for (Future<Long> solutionPart : solutionParts) {
                          if (!solutionPart.isCancelled()) {
                                  result = result + solutionPart.get().longValue();
                          } else {
                                  System.out.println("Sub Task cancelled");
                          }
                  }
                  System.out.println("Complete solution has been found , result is " + result);
          } finally {
                  executorService.shutdown();
          }
  }
}
In the above code we have divided our Input problem into various parts and handed each part to a Participant instance. The invokeAll method takes the collection of these Callables and retuns a Collection of Futures. As per the method's documentation:
Executes the given tasks, returning a list of Futures holding their status and 
results when all complete. Future.isDone is true for each element of the returned 
list. Note that a completed task could have terminated either normally or by 
throwing an exception. The results of this method are undefined if the given collection 
is modified while this operation is in progress.
As seen we have checked the isCancelled flag for each future to see if a successful result was available, before we used it. The invokeAll method blocks until processing of all tasks is complete before returning. The Participant class is as below:
class Participant implements Callable<Long> {

  private int problemPiece;

  public Participant(int problem) {
          this.problemPiece = problem;
  }

  @Override
  public Long call() throws Exception {
          String threadName = "[" + Thread.currentThread().getName() + "]";
          //Start processing
          System.out.println(threadName + " working with " + problemPiece);
          long result = 0;
          for (long i = 0; i < problemPiece; i++) {
                  if (Thread.interrupted()) {
                          System.out.println("Interrupt request received at " + threadName + " to cancel");
                          throw new InterruptedException();
                  }
                  result = result + 1;
          }
          System.out.println("Result computed by " + threadName + " is - " + result);
          return Long.valueOf(result);
  }

}
On execution :
Start solving ..
[pool-1-thread-1] working with 1155484
[pool-1-thread-3] working with 1033096
[pool-1-thread-2] working with 723955
[pool-1-thread-4] working with 1690734
[pool-1-thread-5] working with 1557280
Result computed by [pool-1-thread-2] is - 723955
Result computed by [pool-1-thread-4] is - 1690734
Result computed by [pool-1-thread-3] is - 1033096
Result computed by [pool-1-thread-1] is - 1155484
Result computed by [pool-1-thread-5] is - 1557280
Complete solution has been found , result is 6160549
As seen the solution was formed from the result of tasks executed by all the threads. Similar to invokeAny, there is an overloaded method that could be used:
List<Future<Long>> solutionParts = executorService.invokeAll(participants, 300l, TimeUnit.MILLISECONDS);

No comments:

Post a Comment