Adithya
Adithya

Reputation: 2975

Use of shutdownNow in Concurrent framework

If i am using Futures like

List<Future<String>> results = executorService.invokeAll(tasks); 

or

Future<String> res = executorService.submit(new SingleWorker());
System.out.println(res.get());

the system waits for the tasks to complete.

Even if i had executorService.shutdownNow(); after the statements mentioned above, i really don't understand when will the system forcefully terminate the existing threads as mentioned in the documentation since, the system never reaches the line until the tasks are completed and a future is returned. Am i missing something ? Is there a different test case scenario to test it ?

Will shutdownNow work only with Runnable i.e. when we say executorService.submit(new MyRunnable()) ?

EDIT:

I tried few different things and found out that

a)shutdownNow doesn't work with invokeAll.

b)shutdownNow if present after Future.get then the statement shutdownNow is blocked until Future is resolved (In case of Callable).

c)shutdownNow works perfectly with Runnable.

Following is my code written to test:

class SingleRunnableWorker implements Runnable {

    @Override
    public void run() {
        System.out.println("SingleRunnableWorker Running..");
        try {
            Thread.sleep(10000);
            System.out.println("SingleRunnableWorker Running after sleep..");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

class SingleCallableWorker implements Callable<String> {

    @Override
    public String call() throws Exception {
        System.out.println("SingleCallableWorker Calling..");
        Thread.sleep(10000);
        System.out.println("SingleCallableWorker Calling after sleep..");
        return "SingleCallableWorker Calling done";
    }

}

and i am testing it as follows:

ExecutorService executorService = Executors.newFixedThreadPool(4);
/*List<Future<String>> results = */executorService.invokeAll(tasks);//blocks by default

Future<String> res = executorService.submit(new SingleCallableWorker());
//System.out.println(res.get()); //blocks if uncommented

executorService.submit(new SingleRunnableWorker());

executorService.shutdownNow();

where tasks are all Callables.

Bottomline is invokeAll and Future.get are blocking operations. Can someone please validate ?

Upvotes: 0

Views: 102

Answers (1)

xingbin
xingbin

Reputation: 28269

Both Runnbale and Callable you submitted to ThreadPoolExecutor will be wrappered as java.util.concrrent.FutureTask and executed.

In this case, in both SingleRunnableWorker and SingleCallableWorker, when task is blocked by Thread.sleep(10000), executorService.shutdownNow() will cause InterruptedException be thrown immediately.

But,

  • InterruptedException thrown in SingleRunnableWorker.run() is forced to be catched immediately and handled by e.printStackTrace().
  • InterruptedException thrown in SingleCallableWorker.call() will be catched by inner syncronizer in FutureTask, the syncronizer just record InterruptedException and return. When future.get() is called, the InterruptedException will be wrappered as ExecutionException and re-thrown.

Upvotes: 1

Related Questions