When should I use a CompletionService over an ExecutorService? - java

I just found CompletionService in this blog post. However, this does't really showcases the advantages of CompletionService over a standard ExecutorService. The same code can be written with either. So, when is a CompletionService useful?
Can you give a short code sample to make it crystal clear? For example, this code sample just shows where a CompletionService is not needed (=equivalent to ExecutorService)
ExecutorService taskExecutor = Executors.newCachedThreadPool();
// CompletionService<Long> taskCompletionService =
// new ExecutorCompletionService<Long>(taskExecutor);
Callable<Long> callable = new Callable<Long>() {
#Override
public Long call() throws Exception {
return 1L;
}
};
Future<Long> future = // taskCompletionService.submit(callable);
taskExecutor.submit(callable);
while (!future.isDone()) {
// Do some work...
System.out.println("Working on something...");
}
try {
System.out.println(future.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}

Omitting many details:
ExecutorService = incoming queue + worker threads
CompletionService = incoming queue + worker threads + output queue

With ExecutorService, once you have submitted the tasks to run, you need to manually code for efficiently getting the results of the tasks completed.
With CompletionService, this is pretty much automated. The difference is not very evident in the code you have presented because you are submitting just one task. However, imagine you have a list of tasks to be submitted. In the example below, multiple tasks are submitted to the CompletionService. Then, instead of trying to find out which task has completed (to get the results), it just asks the CompletionService instance to return the results as they become available.
public class CompletionServiceTest {
class CalcResult {
long result ;
CalcResult(long l) {
result = l;
}
}
class CallableTask implements Callable<CalcResult> {
String taskName ;
long input1 ;
int input2 ;
CallableTask(String name , long v1 , int v2 ) {
taskName = name;
input1 = v1;
input2 = v2 ;
}
public CalcResult call() throws Exception {
System.out.println(" Task " + taskName + " Started -----");
for(int i=0;i<input2 ;i++) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
System.out.println(" Task " + taskName + " Interrupted !! ");
e.printStackTrace();
}
input1 += i;
}
System.out.println(" Task " + taskName + " Completed ######");
return new CalcResult(input1) ;
}
}
public void test(){
ExecutorService taskExecutor = Executors.newFixedThreadPool(3);
CompletionService<CalcResult> taskCompletionService = new ExecutorCompletionService<CalcResult>(taskExecutor);
int submittedTasks = 5;
for (int i=0;i< submittedTasks;i++) {
taskCompletionService.submit(new CallableTask (
String.valueOf(i),
(i * 10),
((i * 10) + 10 )
));
System.out.println("Task " + String.valueOf(i) + "subitted");
}
for (int tasksHandled=0;tasksHandled<submittedTasks;tasksHandled++) {
try {
System.out.println("trying to take from Completion service");
Future<CalcResult> result = taskCompletionService.take();
System.out.println("result for a task availble in queue.Trying to get()");
// above call blocks till atleast one task is completed and results availble for it
// but we dont have to worry which one
// process the result here by doing result.get()
CalcResult l = result.get();
System.out.println("Task " + String.valueOf(tasksHandled) + "Completed - results obtained : " + String.valueOf(l.result));
} catch (InterruptedException e) {
// Something went wrong with a task submitted
System.out.println("Error Interrupted exception");
e.printStackTrace();
} catch (ExecutionException e) {
// Something went wrong with the result
e.printStackTrace();
System.out.println("Error get() threw exception");
}
}
}
}

Basically you use a CompletionService if you want to execute multiple tasks in parallel and then work with them in their completion order. So, if I execute 5 jobs, the CompletionService will give me the first one that that finishes. The example where there is only a single task confers no extra value over an Executor apart from the ability to submit a Callable.

I think the javadoc best answers the question of when the CompletionService is useful in a way an ExecutorService isn't.
A service that decouples the production of new asynchronous tasks from the consumption of the results of completed tasks.
Basically, this interface allows a program to have producers which create and submit tasks (and even examine the results of those submissions) without knowing about any other consumers of the results of those tasks. Meanwhile, consumers which are aware of the CompletionService could poll for or take results without being aware of the producers submitting the tasks.
For the record, and I could be wrong because it is rather late, but I am fairly certain that the sample code in that blog post causes a memory leak. Without an active consumer taking results out of the ExecutorCompletionService's internal queue, I'm not sure how the blogger expected that queue to drain.

First of all, if we do not want to waste processor time, we will not use
while (!future.isDone()) {
// Do some work...
}
We must use
service.shutdown();
service.awaitTermination(14, TimeUnit.DAYS);
The bad thing about this code is that it will shut down ExecutorService. If we want to continue work with it (i.e. we have some recursicve task creation), we have two alternatives: invokeAll or ExecutorService.
invokeAll will wait untill all tasks will be complete. ExecutorService grants us ability to take or poll results one by one.
And, finily, recursive example:
ExecutorService executorService = Executors.newFixedThreadPool(THREAD_NUMBER);
ExecutorCompletionService<String> completionService = new ExecutorCompletionService<String>(executorService);
while (Tasks.size() > 0) {
for (final Task task : Tasks) {
completionService.submit(new Callable<String>() {
#Override
public String call() throws Exception {
return DoTask(task);
}
});
}
try {
int taskNum = Tasks.size();
Tasks.clear();
for (int i = 0; i < taskNum; ++i) {
Result result = completionService.take().get();
if (result != null)
Tasks.add(result.toTask());
}
} catch (InterruptedException e) {
// error :(
} catch (ExecutionException e) {
// error :(
}
}

See it by yourself at run time,try to implement both solutions (Executorservice and Completionservice) and you'll see how different they behave and it will be more clear on when to use one or the other.
There is an example here if you want http://rdafbn.blogspot.co.uk/2013/01/executorservice-vs-completionservice-vs.html

Let's say you have 5 long running task(callable task) and you have submitted those task to executer service. Now imagine you don't want to wait for all 5 task to compete instead you want to do some sort of processing on these task if any one completes. Now this can be done either by writing polling logic on future objects or use this API.

package com.barcap.test.test00;
import java.util.concurrent.*;
/**
* Created by Sony on 25-04-2019.
*/
public class ExecutorCompletest00 {
public static void main(String[] args) {
ExecutorService exc= Executors.newFixedThreadPool( 10 );
ExecutorCompletionService executorCompletionService= new ExecutorCompletionService( exc );
for (int i=1;i<10;i++){
Task00 task00= new Task00( i );
executorCompletionService.submit( task00 );
}
for (int i=1;i<20;i++){
try {
Future<Integer> future= (Future <Integer>) executorCompletionService.take();
Integer inttest=future.get();
System.out.println(" the result of completion service is "+inttest);
break;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
=======================================================
package com.barcap.test.test00;
import java.util.*;
import java.util.concurrent.*;
/**
* Created by Sony on 25-04-2019.
*/
public class ExecutorServ00 {
public static void main(String[] args) {
ExecutorService executorService=Executors.newFixedThreadPool( 9 );
List<Future> futList= new ArrayList <>( );
for (int i=1;i<10;i++) {
Future result= executorService.submit( new Task00( i ) );
futList.add( result );
}
for (Future<Integer> futureEach :futList ){
try {
Integer inm= futureEach.get();
System.out.println("the result of future executorservice is "+inm);
break;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
}
===========================================================
package com.barcap.test.test00;
import java.util.concurrent.*;
/**
* Created by Sony on 25-04-2019.
*/
public class Task00 implements Callable<Integer> {
int i;
public Task00(int i) {
this.i = i;
}
#Override
public Integer call() throws Exception {
System.out.println(" the current thread is "+Thread.currentThread().getName() +" the result should be "+i);
int sleepforsec=100000/i;
Thread.sleep( sleepforsec );
System.out.println(" the task complted for "+Thread.currentThread().getName() +" the result should be "+i);
return i;
}
}
======================================================================
difference of logs for executor completion service:
the current thread is pool-1-thread-1 the result should be 1
the current thread is pool-1-thread-2 the result should be 2
the current thread is pool-1-thread-3 the result should be 3
the current thread is pool-1-thread-4 the result should be 4
the current thread is pool-1-thread-6 the result should be 6
the current thread is pool-1-thread-5 the result should be 5
the current thread is pool-1-thread-7 the result should be 7
the current thread is pool-1-thread-9 the result should be 9
the current thread is pool-1-thread-8 the result should be 8
the task complted for pool-1-thread-9 the result should be 9
teh result is 9
the task complted for pool-1-thread-8 the result should be 8
the task complted for pool-1-thread-7 the result should be 7
the task complted for pool-1-thread-6 the result should be 6
the task complted for pool-1-thread-5 the result should be 5
the task complted for pool-1-thread-4 the result should be 4
the task complted for pool-1-thread-3 the result should be 3
the task complted for pool-1-thread-2 the result should be 2
the current thread is pool-1-thread-1 the result should be 1
the current thread is pool-1-thread-3 the result should be 3
the current thread is pool-1-thread-2 the result should be 2
the current thread is pool-1-thread-5 the result should be 5
the current thread is pool-1-thread-4 the result should be 4
the current thread is pool-1-thread-6 the result should be 6
the current thread is pool-1-thread-7 the result should be 7
the current thread is pool-1-thread-8 the result should be 8
the current thread is pool-1-thread-9 the result should be 9
the task complted for pool-1-thread-9 the result should be 9
the task complted for pool-1-thread-8 the result should be 8
the task complted for pool-1-thread-7 the result should be 7
the task complted for pool-1-thread-6 the result should be 6
the task complted for pool-1-thread-5 the result should be 5
the task complted for pool-1-thread-4 the result should be 4
the task complted for pool-1-thread-3 the result should be 3
the task complted for pool-1-thread-2 the result should be 2
the task complted for pool-1-thread-1 the result should be 1
the result of future is 1
=======================================================
for executorservice the result will only be avialable after all tasks complted.
executor completionservice any result avilable make that return.

If the task producer is not interested in the results and it is another component's responsibility to process results of asynchronous task executed by executor service, then you should use CompletionService. It helps you in separating task result processor from task producer. See example http://www.zoftino.com/java-concurrency-executors-framework-tutorial

there is another advantage of using completionservice: Performance
when you call future.get(), you are spin waiting:
from java.util.concurrent.CompletableFuture
private Object waitingGet(boolean interruptible) {
Signaller q = null;
boolean queued = false;
int spins = -1;
Object r;
while ((r = result) == null) {
if (spins < 0)
spins = (Runtime.getRuntime().availableProcessors() > 1) ?
1 << 8 : 0; // Use brief spin-wait on multiprocessors
else if (spins > 0) {
if (ThreadLocalRandom.nextSecondarySeed() >= 0)
--spins;
}
when you have a long-running task, this will be a disaster for performance.
with completionservice, once the task is done, it's result will be enqueued and you can poll the queue with lower performance overhand.
completionservice achieve this by using wrap task with a done hook.
java.util.concurrent.ExecutorCompletionService
private class QueueingFuture extends FutureTask<Void> {
QueueingFuture(RunnableFuture<V> task) {
super(task, null);
this.task = task;
}
protected void done() { completionQueue.add(task); }
private final Future<V> task;
}

assuming you execute a tasks in parallel and you save the Future results in a list:
The practical main difference between ExecutorService and CompletionService is:
ExecutorService get() will try to retrieve the results in the submitted order waiting for completion.
CompletionService take() + get() will try to retrieve the results in the completion order disregarding the submission order.

ExecutorCompletionService class implements CompletionService.
ExecutorCompletionService returns futures objects based on completion order, so whichever task executes first, will be returned first. You just need to call executorCompletionService.take() to get completed Future object.
I found a blog that clear my thought.
java2blog link with example

Related

Testing RejectedExecutionHandler in ThreadPoolExecutor

How i can make sure that my rejectedExecution method works
RejectedExecutionHandler() {
#Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
logger.log(Level.INFO, "Name_[" + executorServiceName + "]: All threads busy, processing inline.");
r.run();
}
});
I would personally create a situation where my ExecutorService will always reject a task and check that this task has been called using a counter.
So for example my code could be something like that:
// A single threaded executor service that cannot have more than 1 task in its task queue
// such that I know that if I provide at least 3 tasks, at least 1 task will be rejected.
// Why 3? 1 task in the queue + 1 task executed by the thread of the pool
// = max of tasks that the pool can manage at a given time, so if I add 1 it will be
// rejected.
ExecutorService executor = new ThreadPoolExecutor(
1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(1),
Executors.defaultThreadFactory(), myHandler
);
// My Counter
AtomicInteger counter = new AtomicInteger();
// Some arbitrary task that lasts long enough to make sure that at least 3
// tasks will be submitted that will increment my counter once completed
Runnable task = () -> {
try {
Thread.sleep(1_000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
counter.incrementAndGet();
}
};
try {
// Submit 3 tasks
executor.submit(task);
executor.submit(task);
executor.submit(task);
} finally {
// Shutdown the pool and wait until all the submitted tasks have been executed
executor.shutdown();
executor.awaitTermination(1L, TimeUnit.MINUTES);
}
// Ensure that we have 3 tasks that have been executed
assertEquals(3, counter.get());

Callable sequential execution

I know Callable allows to return a value or checked exception whereas Runnable doesn't. This question is not about the difference between the two interfaces but about the sequential returns of the values in following code.
Please have a look at the following code segment.
ExecutorService executorService = Executors.newCachedThreadPool();
List<Future<String>> futureList = new ArrayList<Future<String>>();
for (int i=0;i<10;i++) {
Runner runner = new Runner(i);
Future<String> future = executorService.submit(runner);
futureList.add(future);
}
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.DAYS);
for (Future<String> integerFuture : futureList) {
System.out.println("Returned value is : " + integerFuture.get());
}
The Runner class for this code is provided below.
public class Runner implements Callable<String> {
private int id;
public Runner(Integer id) {
this.id = id;
}
#Override
public String call() throws Exception {
Random randomWait = new Random();
Thread.sleep(randomWait.nextInt(5)*1000);
Random random = new Random();
int randomInt = random.nextInt(100);
return id + " - " + randomInt;
}
}
The above code always provides a sequential response despite the fact that the threads executing them may sleep different seconds.
Returned value is : 0 - 19
Returned value is : 1 - 88
Returned value is : 2 - 99
........
Returned value is : 9 - 42
But by comparison the following code segment provides more meaningful response, as the threads sleeps different time periods.
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i=0;i<10;i++) {
Runner runner = new Runner(i);
executorService.submit(runner);
}
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.DAYS);
The runner class for about segment is given below.
public class Runner implements Runnable {
private int id;
public Runner(Integer id) {
this.id = id;
}
#Override
public void run() {
Random randomWait = new Random();
try {
Thread.sleep(randomWait.nextInt(5)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Runner : " + id + " Finished.");
}
}
As expected the response of this thread was non sequential.
Runner : 5 Finished.
Runner : 9 Finished.
Runner : 1 Finished.
Runner : 3 Finished.
........
So my question is why does the fist code segment with futures and callable response is always sequential ? It seems to me that the main thread waits till end end of executing all the threads and provides a sequential output. But there is nothing about it is mentioned in the javadoc. If the response was something like second one I could have understood it.
First you explicitly create the list of futures with ordered IDs, then you iterate over it in order:
for (Future<String> integerFuture : futureList) {
System.out.println("Returned value is : " + integerFuture.get());
There is no other possible result but sequential IDs. Each time you call integerFuture.get(), the call will block as long as needed for the future to provide the result.
In the second example you output to the console from within the Callable, thus you get output in the order of completion.
So my question is why does the fist code segment with futures and callable response is always sequential?
Because you're specifically asking for the result of the Futures in the order in which they were submitted:
for (Future<String> integerFuture : futureList) {
System.out.println("Returned value is : " + integerFuture.get());
Here, Future.get() will block until the call has completed - and your list is constructed by submitting callables; futureList.get(0) is always going to be the future related to the first callable submitted, regardless of whether it's the first one to complete.

ExecutorService invokeall threadpool issue

I am struggling with a use case where one of the tasks submitted to invokeall() throws CancellationException forcing program NOT to terminate. How can make sure this program will terminate properly in case of CancellationException ?
How I am finding out my program not terminated clean? I am using netbeans and shows progress bar at bottom right if program doesn't terminate.
Here is code:
int poolSize = Runtime.getRuntime().availableProcessors();
ExecutorService pool = Executors.newFixedThreadPool(poolSize);
Set<Callable<Object>> tasksSet = new HashSet<>();
tasksSet.add(new Task1());
tasksSet.add(new Task2());
tasksSet.add(new Task3());
List<Future<TrendLineStatisticsVO>> resultSet = pool.invokeAll(tasksSet, 1, TimeUnit.MINUTES);
for (Future<Object> future : resultSet) {
Object result;
try {
result = future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
} catch (TimeoutException ex) {
ex.printStackTrace();
Logger.getLogger(CallableDemo.class.getName()).log(Level.SEVERE, null, ex);
}
}
pool.shutdown();
And Task1 code:
public class Task1 implements Callable<Object> {
#Override
public Object call() throws Exception {
//This for sure takes days to complete, so should through Cancellation exception because timeout on invokeall set to 1 minute
long val = 0;
for (long i = 0; i < Long.MAX_VALUE - 5000; i++) {
val += i;
}
return "Sucessfull Task1 object...";
}
}
Task2 and Task3 code also same except these two classes use Integer.MAX_VALUE in for loop check.
There are two issues:
1)
Per the Javadoc:
tasks that have not completed are cancelled.
So you will have to code your Task to be responsive to interruption. What is happening in the background is similar to future.cancel(true) if the tasks don't complete in the time specified, the true in the argument says to interrupt() the thread running the task. Like I mentioned, your tasks will have to look out for interruption. Something similar to:
#Override
public Object call() throws Exception {
//This for sure takes days to complete, so should through Cancellation exception because timeout on invokeall set to 1 minute
long val = 0;
for (long i = 0; i < Long.MAX_VALUE - 5000; i++) {
if(Thread.interruped()){
throw new RuntimeException("Did not complete in time: " + i);
}
val += i;
}
return "Sucessfull Task1 object...";
}
How I am finding out my program not terminated clean? I am using netbeans and shows progress bar at bottom right if program doesn't terminate.
Without my update above the program will never end as the thread pool is still running. shutdown will do nothing as the tasks haven't completed (event with cancel).
2)
A task that is cancelled, by definition, did not complete (or even start) so invoking get on the Future will fail quickly. You could ask the future if it's cancelled Future#isCancelled.

Not calling get on list of futures

I'm using a global Executor service with some fixed thread pool size. We have bunch of related tasks that we submit for execution and wait on list of futures.
Recently, we faced a high CPU utilization issue and on debugging I found that an exception occurred while calling get() on one of the item in list of futures. Current, we iterate over the list and there is a try catch surrounding the whole loop.
try{
List<Result> results = new ArrayList<>()
for(Future<Result> futureResult: futureResults{
Result result = futureResult.get();
results.add(result);
}
} catch(Exception e){
throw new InternalServiceException(e);
}
//Do something with results
Wanted to know the behaviour of other threads if get is never called on some of the items in future. I tried searching but was not able to find anything.
Also, can this behaviour trigger high CPU utilization ?
http://www.journaldev.com/1650/java-futuretask-example-program
I would still check if the future isDone as in the example above.
If you need to run other operations or want to utilize the CPU better then I would put the collector in a separate thread and perhaps just poll for results every minute or so.
Could be scheduled or handled by Thread.sleep.
Executors class provides various methods to execute Callable in a thread pool. Since callable tasks run in parallel, we have to wait for the returned Object.
Callable tasks return java.util.concurrent.Future object. Using Future we can find out the status of the Callable task and get the returned Object.
It provides get() method that can wait for the Callable to finish and then return the result.
There is an overloaded version of get() method where we can specify the time to wait for the result, it’s useful to avoid current thread getting blocked for longer time.
Future provides cancel() method to cancel the associated Callable task. There are isDone() and isCancelled() methods to find out the current status of associated Callable task.
Here is a simple example of Callable task that returns the name of thread executing the task after some random time.
We are using Executor framework to execute 10 tasks in parallel and use Future to get the result of the submitted tasks.
public class FutureObjectTest implements Callable<String>{
#Override
public String call() throws Exception {
long waitTime = (long) (Math.random()*10000);
System.out.println(Thread.currentThread().getName() + " waiting time in MILISECONDS " + waitTime);
Thread.sleep(waitTime);
return Thread.currentThread().getName() + " exiting call method.";
}
public static void main(String [] args){
List<Future<String>> futureObjectList = new ArrayList<Future<String>>();
ExecutorService executorService = Executors.newFixedThreadPool(5);
Callable<String> futureObjectTest = new FutureObjectTest();
for(int i=0; i<10; i++){
Future<String> futureResult = executorService.submit(futureObjectTest);
futureObjectList.add(futureResult);
}
for(Future<String> futureObj : futureObjectList){
try {
System.out.println(futureObj.get());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
}
System.out.println("Starting get method of wait");
////////////get(Timeout) method///////
futureObjectList.clear();
for(int i=0; i<10; i++){
Future<String> futureResult = executorService.submit(futureObjectTest);
futureObjectList.add(futureResult);
}
executorService.shutdown();
for(Future<String> futureObj : futureObjectList){
try {
System.out.println(futureObj.get(2000,TimeUnit.MILLISECONDS));
} catch (InterruptedException | ExecutionException | TimeoutException e) {
e.printStackTrace();
}
}
}
}

Multithreaded approach using java Executor interface

I am trying to implement the multithreaded approach using executor interface where i have produced multiple threads in main class
class Main
{
private static final int NTHREADS = 10;
public static void main(String[] args)
{
.........
String str = createThreads(document);
.............
}
public String createThreads(String docString)
{
........
.......
Map<String,String> iTextRecords = new LinkedHashMap<String, String>();
if(!iText.matches(""))
{
String[] tokenizedItext = iText.split("\\^");
ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
for(int index = 0 ;index < tokenizedItext.length;index++)
{
Callable<Map<String,String>> worker = null;
Future<Map<String,String>> map = null;
if(tokenizedItext[index].matches("^[0-9.<>+-= ]+$") || tokenizedItext[index].matches("^\\s+$"))
{
iTextRecords.put(tokenizedItext[index],tokenizedItext[index]);
}
else
{
worker = new MultipleDatabaseCallable(tokenizedItext[index],language);
map = executor.submit(worker);
try
{
iTextRecords.putAll(map.get());
}
catch(InterruptedException ex)
{
ex.printStackTrace(System.out);
}
catch(ExecutionException ex)
{
ex.printStackTrace(System.out);
}
}
}
executor.shutdown();
// Wait until all threads are finish
while (!executor.isTerminated())
{
}
}
}
The Callable class is as
class MultipleDatabaseCallable implements Callable<Map<String,String>>
{
#Override
public Map<String, String> call() throws Exception {
System.out.println("Entering: "+Thread.currentThread().getName());
Map<String,String> map = new HashMap<String,String>();
for(int i =0;i<50000;i++)
{
for(int i1 = 0 ;i1<5000;i1++)
{
for(int i2 =0;i2 <500;i2++)
{
}
}
}
System.out.println("Exiting: "+Thread.currentThread().getName());
return map;
}
}
output I am getting is
Entering: pool-1-thread-1
Exiting: pool-1-thread-1
Entering: pool-1-thread-2
Exiting: pool-1-thread-2
Entering: pool-1-thread-3
Exiting: pool-1-thread-3
Entering: pool-1-thread-4
Exiting: pool-1-thread-4
Entering: pool-1-thread-5
Exiting: pool-1-thread-5
Entering: pool-1-thread-6
Exiting: pool-1-thread-6
While looking at the output it seems like only one thread is entering at a time in the call method and other thread enters only when previous one exist. However it is expected that the multiple threads should enter and execute call() method. Also when I am executing the same program by making NTHREADS = 1. it is taking same time as it is taking with NTHREADS =10
so it seems like the application is running as good as a single threaded application.please suggest whats wrong i am doing in implementation.
Thanks
When you call
map = executor.submit(worker);
the value returned map in this case is a Future. Meaning that it does not have a value, until the callable has returned one. Now when you call
iTextRecords.putAll(map.get());
What happens is that the current thread blocks (inside the map.get()) waiting for the callable to return (in the other thread).
Since you always wait for a callable to be finished (per map.get()) before submitting a new one (per executor.submit()) you enforce the sequential execution you observe.
In order to execute the tasks in parallel, you have to start them all before calling get for the first time. You could for instance create an ArrayList<Future<Map<String,String>>> futures = ... and then
do
futures.add(executor.submit(worker));
to submit the tasks (no need for the map variable) and create a second loop (after the for(int i ...) loop):
for(Future<Map<String,String>> f: futures) {
iTextRecords.putAll(f.get);
}
You must collect your futures while you submit the callables. Call get() on your futures only after you finish submitting.

Categories

Resources