Question

Whenever i run my program implementing callable, i get the output in a sequential form.

Like, here is my program :

package com.handson;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class WorkSheet_1 implements Callable<String> {

    /**
     * @param args
     */
    private int id;
    static int count = 0;
    public static String test[] = { "a1" , "a2" , "a3" , "a4" , "a5" , "a6" , "a7" , "a8" ,
                                    "b1" , "b2" , "b3" , "b4" , "b5" , "b6" , "b7" , "b8" ,
                                    "c1" , "c2" , "c3" , "c4" , "c5" , "c6" , "c7" , "c8" ,
                                    "d1" , "d2" , "d3" , "d4" , "d5" , "d6" , "d7" , "d8" ,
                                    "e1" , "e2" , "e3" , "e4" , "e5" , "e6" , "e7" , "e8" ,
                                    "f1" , "f2" , "f3" , "f4" , "f5" , "f6" , "f7" , "f8" ,
                                    "g1" , "g2" , "g3" , "g4" , "g5" , "g6" , "g7" , "g8" ,
                                    "h1" , "h2" , "h3" , "h4" , "h5" , "h6" , "h7" , "h8"}; 
    public WorkSheet_1(int id){
        this.id = id;
    }

    public static void main(String[] args) {
        try{
        // TODO Auto-generated method stub
            BlockingQueue blockingQueue = new ArrayBlockingQueue<WorkSheet_1>(48);
            ThreadPoolExecutor testExecutor = new ThreadPoolExecutor(6, 10, 1, TimeUnit.SECONDS, blockingQueue);
            for(int i = 0 ;i < test.length ;i++){
                Future<String> testFuture = testExecutor.submit(new WorkSheet_1(i));
                try {
                    System.out.println("Output Returned is : "+testFuture.get());
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }catch(RejectedExecutionException e){
            e.printStackTrace();
        }
    }

    @Override
    public String call() throws Exception {
        // TODO Auto-generated method stub
        return "Called "+test[this.id];
    }



}

CALLABLE OUTPUT :

Output Returned is : Called a1
Output Returned is : Called a2
Output Returned is : Called a3
Output Returned is : Called a4
Output Returned is : Called a5
Output Returned is : Called a6
Output Returned is : Called a7
Output Returned is : Called a8
Output Returned is : Called b1
Output Returned is : Called b2
Output Returned is : Called b3
Output Returned is : Called b4
Output Returned is : Called b5
Output Returned is : Called b6
Output Returned is ...............

Output always prints the array sequentially whereas when i implement runnable output is in any order :

RUNNABLE OUTPUT :

Output Returned is : Called a1
Output Returned is : Called a3
Output Returned is : Called a7
Output Returned is : Called a8
Output Returned is : Called b1
Output Returned is : Called b2
Output Returned is : Called b3
Output Returned is : Called b4 ..............

Why such a difference ?

Was it helpful?

Solution 3

Using CompletionService we dont need to print Sysout in call function(as Provided by @Patricia) and there is a benefit of using CompletionService than Futures.

For more info refer java-concurrency-executors-and-thread-pools. The site stated,

"Code using future is bit complicated. And there is a disadvantage. If the first task takes a long time to compute and all the other tasks ends before the first, the current thread cannot compute the result before the first task ends.Solution for this problem is Completion Service"

Now Solution using Sompletion Service print the desired result :

    BlockingQueue<Runnable> blockingQueue   blockingQueue = new ArrayBlockingQueue<WorkSheet_1>(48);
    ThreadPoolExecutor testExecutor = new ThreadPoolExecutor(6, 16, 1,
            TimeUnit.SECONDS, blockingQueue, new CustomThreadFactory());

    CompletionService<String> completionService = new ExecutorCompletionService<String>(
            testExecutor);

    for (int i = 0; i < test.length; i++) {
        completionService.submit(new WorkSheet_1(i));
    }

    for (int i = 0; i < test.length; i++) {
        try {
            String result = completionService.take().get();
            System.out.println("Output Returned is : " + result);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (ExecutionException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        // Compute the result
    }

OTHER TIPS

Because you wait for the result of the callable in the for loop:

  System.out.println("Output Returned is : "+testFuture.get());

The Future.get() method will block until the result is available. So you submit the next Callable only after the previous result is available.

To see interleaving of the output you need to make two changes.

The first, based on the previous answer, is to move the waiting for completion out of the loop that queues the tasks. Doing so allows the Callables to run in parallel, rather than forcing a wait for return value after each one. The return values are still reported in the order in which they were queued up.

The second change is to have each Callable produce some output while it is being run. If you only output from the main thread on completion, the output must be in the order in which you wait for completion.

Because Runnable does not produce a return value, I am sure the Runnable form of the test, in effect, did both these changes. They would have to supply their own output while running, rather than returning a result. There would be no reason to wait for each of them to finish.

Here is a test program, based on the original program, with those changes:

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class Test implements Callable<String> {

  /**
   * @param args
   */
  private int id;
  static int count = 0;
  public static String test[] = { "a1", "a2", "a3", "a4", "a5", "a6", "a7",
      "a8",
      "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8",
      "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8",
      "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8",
      "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8",
      "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8",
      "g1", "g2", "g3", "g4", "g5", "g6", "g7", "g8",
      "h1", "h2", "h3", "h4", "h5", "h6", "h7", "h8" };

  public Test(int id) {
    this.id = id;
  }

  public static void main(String[] args) {
    try {
      // TODO Auto-generated method stub
      BlockingQueue<Runnable> blockingQueue = new ArrayBlockingQueue<Runnable>(
          48);
      ThreadPoolExecutor testExecutor = new ThreadPoolExecutor(6, 10, 1,
          TimeUnit.SECONDS, blockingQueue);
      List<Future<String>> futures = new ArrayList<>();
      for (int i = 0; i < test.length; i++) {
        Future<String> testFuture = testExecutor.submit(new Test(i));
        futures.add(testFuture);
      }
      for (Future<String> testFuture : futures) {
        try {
          System.out.println("Output Returned is : " + testFuture.get());
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        } catch (ExecutionException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    } catch (RejectedExecutionException e) {
      e.printStackTrace();
    }
  }

  @Override
  public String call() throws Exception {
    System.out.println("Running " + test[this.id]);
    return "Called " + test[this.id];
  }

}

Sample output:

Running a1
Running a3
Running a2
Running a4
Running a5
Running a6
Running a7
Running b1
Running b5
Running a8
Running b7
Running b6
Running b2
Running b4
Running b3
Running c4
Running c3
Running c2
Running c1
Running b8
Running d1
Running c8
Running c7
Running c6
Output Returned is : Called a1
Output Returned is : Called a2
Output Returned is : Called a3
Running c5
Output Returned is : Called a4
Running d6
Running d5
Running d4
Running d3
Running d2
Running e3
Running e2
Running e1
Running d8
Output Returned is : Called a5
Running d7
Output Returned is : Called a6
Running e8
Running e7
Running e6
Running e5
Running e4
Running f5
Running f4
Running f3
Running f2
Output Returned is : Called a7
Running f1
Output Returned is : Called a8
Running g2
Running g1
Running f8
Running f7
Running f6
Running g7
Running g6
Running g5
Running g4
Output Returned is : Called b1
Running g3
Output Returned is : Called b2
Running h4
Running h3
Running h2
Running h1
Running g8
Running h8
Running h7
Running h6
Output Returned is : Called b3
Running h5
Output Returned is : Called b4
Output Returned is : Called b5
Output Returned is : Called b6
Output Returned is : Called b7
Output Returned is : Called b8
Output Returned is : Called c1
Output Returned is : Called c2
Output Returned is : Called c3
Output Returned is : Called c4
Output Returned is : Called c5
Output Returned is : Called c6
Output Returned is : Called c7
Output Returned is : Called c8
Output Returned is : Called d1
Output Returned is : Called d2
Output Returned is : Called d3
Output Returned is : Called d4
Output Returned is : Called d5
Output Returned is : Called d6
Output Returned is : Called d7
Output Returned is : Called d8
Output Returned is : Called e1
Output Returned is : Called e2
Output Returned is : Called e3
Output Returned is : Called e4
Output Returned is : Called e5
Output Returned is : Called e6
Output Returned is : Called e7
Output Returned is : Called e8
Output Returned is : Called f1
Output Returned is : Called f2
Output Returned is : Called f3
Output Returned is : Called f4
Output Returned is : Called f5
Output Returned is : Called f6
Output Returned is : Called f7
Output Returned is : Called f8
Output Returned is : Called g1
Output Returned is : Called g2
Output Returned is : Called g3
Output Returned is : Called g4
Output Returned is : Called g5
Output Returned is : Called g6
Output Returned is : Called g7
Output Returned is : Called g8
Output Returned is : Called h1
Output Returned is : Called h2
Output Returned is : Called h3
Output Returned is : Called h4
Output Returned is : Called h5
Output Returned is : Called h6
Output Returned is : Called h7
Output Returned is : Called h8

The "Running xx" messages start out more or less in order, but quickly get out of order.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top