ExecutorService.awaitTermination runs into timeout despite active tasks - java

I have the following implementation:
final ExecutorService service = Executors.newFixedThreadPool(4);
final List<Callable> taskList = new LinkedList<>();
for (Path path : paths) {
final SomeCallable task = new SomeCallable(path);
taskList.add(task);
service.submit(task);
}
synchronized (this) {
try {
this.wait();
shutdown(service);
} catch (InterruptedException e) {
shutdown(service);
}
}
And the following shutdown(service) method:
protected void shutdown(final ExecutorService service) {
List<Runnable> abortedCallables = service.shutdownNow();
try {
if (!service.awaitTermination(2, TimeUnit.MINUTES)) {
System.out.println("timeout");
}
}
catch (InterruptedException e) {
// (Re-)cancel all Callables if current thread has been interrupted
service.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
My problem is the following: paths is a list of a lot of Path instances. All of these paths will undergo some processing within a SomeCallable instance. Usually, this thread waits until all paths have been successfully handled within their SomeCallable. Once all paths have been processed shutdown(service) will be called.
However, it may happen that this thread is interrupted and has to be shutdown immediately. Therefore, I call shutdown(service) within the catch-block. What is working is, that currently running SomeCallable-instances will be finished and none of the tasks within the ExecutorService's thread pool will be started. Nonetheless, awaitTermination always runs into the 2 minute timeout. Why is this?
I assumed that awaitTermination waits for currently active running tasks to terminate (hence, wait for a maximum of 4 tasks -> thread pool size). Two minutes - in my case - is more than enough time for the 4 tasks to finish. As by calling shutdownNow() no new tasks from the queue should be started I wonder why I still get the timeout.
Any ideas?

Related

Future.cancel() followed by Future.get() kills my thread

I want to use the Executor interface (using Callable) in order to start a Thread (let's call it callable Thread) which will do work that uses blocking methods.
That means the callable Thread can throw an InterruptedException when the main Thread calls the Future.cancel(true) (which calls a Thread.interrupt()).
I also want my callable Thread to properly terminate when interrupted USING other blocking methods in a cancellation part of code.
While implementing this, I experienced the following behavior: When I call Future.cancel(true) method, the callable Thread is correctly notified of the interruption BUT if the main Thread immediately waits for its termination using Future.get(), the callable Thread is kind of killed when calling any blocking method.
The following JUnit 5 snippet illustrates the problem.
We can easily reproduce it if the main Thread does not sleep between the cancel() and the get() calls.
If we sleep a while but not enough, we can see the callable Thread doing half of its cancellation work.
If we sleep enough, the callable Thread properly completes its cancellation work.
Note 1: I checked the interrupted status of the callable Thread: it is correctly set once and only once, as expected.
Note 2: When debugging step by step my callable Thread after interruption (when passing into the cancellation code), I "loose" it after several step when entering a blocking method (no InterruptedException seems to be thrown).
#Test
public void testCallable() {
ExecutorService executorService = Executors.newSingleThreadExecutor();
System.out.println("Main thread: Submitting callable...");
final Future<Void> future = executorService.submit(() -> {
boolean interrupted = Thread.interrupted();
while (!interrupted) {
System.out.println("Callable thread: working...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.out.println("Callable thread: Interrupted while sleeping, starting cancellation...");
Thread.currentThread().interrupt();
}
interrupted = Thread.interrupted();
}
final int steps = 5;
for (int i=0; i<steps; ++i) {
System.out.println(String.format("Callable thread: Cancelling (step %d/%d)...", i+1, steps));
try {
Thread.sleep(200);
} catch (InterruptedException e) {
Assertions.fail("Callable thread: Should not be interrupted!");
}
}
return null;
});
final int mainThreadSleepBeforeCancelMs = 2000;
System.out.println(String.format("Main thread: Callable submitted, sleeping %d ms...", mainThreadSleepBeforeCancelMs));
try {
Thread.sleep(mainThreadSleepBeforeCancelMs);
} catch (InterruptedException e) {
Assertions.fail("Main thread: interrupted while sleeping.");
}
System.out.println("Main thread: Cancelling callable...");
future.cancel(true);
System.out.println("Main thread: Cancelable just cancelled.");
// Waiting "manually" helps to test error cases:
// - Setting to 0 (no wait) will prevent the callable thread to correctly terminate;
// - Setting to 500 will prevent the callable thread to correctly terminate (but some cancel process is done);
// - Setting to 1500 will let the callable thread to correctly terminate.
final int mainThreadSleepBeforeGetMs = 0;
try {
Thread.sleep(mainThreadSleepBeforeGetMs);
} catch (InterruptedException e) {
Assertions.fail("Main thread: interrupted while sleeping.");
}
System.out.println("Main thread: calling future.get()...");
try {
future.get();
} catch (InterruptedException e) {
System.out.println("Main thread: Future.get() interrupted: Error.");
} catch (ExecutionException e) {
System.out.println("Main thread: Future.get() threw an ExecutionException: Error.");
} catch (CancellationException e) {
System.out.println("Main thread: Future.get() threw an CancellationException: OK.");
}
executorService.shutdown();
}
When you call get() on a canceled Future, you will get a CancellationException, hence will not wait for the Callable’s code to perform its cleanup. Then, you are just returning and the observed behavior of threads being killed seems to be part of JUnit’s cleanup when it has determined that the test has completed.
In order to wait for the full cleanup, change the last line from
executorService.shutdown();
to
executorService.shutdown();
executorService.awaitTermination(1, TimeUnit.DAYS);
Note that it is simpler to declare unexpected exceptions in the method’s throws clause rather than cluttering your test code with catch clauses calling Assertions.fail. JUnit will report such exceptions as failure anyway.
Then, you can remove the entire sleep code.
It might be worth putting the ExecutorService management into #Before/#After or even #BeforeClass/#AfterClass methods, to keep the testing methods free of that, to focus on the actual tests.¹
¹ These were the JUnit 4 names. IIRC, the JUnit 5 names are like #BeforeEach/#AfterEach resp. #BeforeAll/#AfterAll

How to ensure the tasks in the pool should get finish before the program exits?

I am currently working on a multi threaded document similarity program. Simply put this extract of the program gets an object, passes it to a "hasher" method ,minhashes a value of the object and adds it to a list to be manipulated in order to test similarity .
My issue is that the main thread seems to advance to where I manipulate the list whilst the threads from the pool are still running and minhashing the object values,using println I could see that the program had ran till to the end but the threads were still executing in the run() method after.
How can I ensure that the tasks in the pool should get finished before the program advances?
int docCount = 2;
while (docCount > 0) {
try {
Shingle s = q.take();
if (s instanceof Poisin == false) {
pool.execute(new Runnable() {
#Override
public void run() {
System.out.println("DEBUG : currently in run()" + Thread.currentThread());
if (s.getDocumentId() == 1) {
list1.add(hasher(s));
} else if (s.getDocumentId() == 2) {
list2.add(hasher(s));
} else {
voidList.add(hasher(s));
}
}
});// Runnable
} else {
docCount--;
}
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("INteruppted exception " + e);
}
}
float k1 = list1.size();
float k2 = list2.size();
System.out.println("DEBUG : End of program" + Thread.currentThread());
How can I ensure that the tasks in the pool have completed before the
program advances?
Use to initiates an orderly shutdown in which previously submitted tasks are executed, you need to call below methods after submitting tasks to executor. Because, calling shutdown will reject any new task afterward.
pool.shutdown();
Then after
pool.awaitTermination(60, TimeUnit.SECONDS) // specify timeout here
On Oracle documentation page, it was very well documented with an example (copied) :
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
Above, method will ensure, there are no new task submitted and will wait for atmost 60 seconds to finish all tasks.
Try shutting down the executor service and waiting for all the threads to terminate before trying to process your results.
<Submit work to thread pool>
..
executorService.shutdownNow();
executorService.awaitTermination();
..
<Process results from threads>

How to exit ExecutorService after all the threads have done their execution? [duplicate]

This question already has answers here:
How to properly shutdown java ExecutorService
(2 answers)
Closed 5 years ago.
This is the code which is working but I am specifying the wait time explicitly. Is there any way to exit ExecutorService when all the threads have completed their execution.
ExecutorService es = Executors.newCachedThreadPool();
{
for(final List<String> list:partitions){
es.execute(new Runnable() {
public void run() {
try{
System.out.println(list);
new CallAPI().make_call(list, access_token);
}catch(Exception e){
System.out.println(e);
}
}
});
Thread.sleep(5000);
}
boolean finshed = es.awaitTermination(15, TimeUnit.MINUTES);
es.shutdown();
boolean finshed = es.awaitTermination(15, TimeUnit.MINUTES);==>I am giving here wait time but I don't want this because I don't know when the thread will finish execution
use Future<?> f = executor.submit(new Runnable(...));
store the futures in a list
after the loop, iterate over the futures and call f.get()
This will block until all the tasks have been executed.
You can then call executor.shutdown().
It sounds like you want ExecutorService.invokeAll. All you have to do is convert your collection of lists to a collection of Callables.
List<Callable<String>> tasks = partitions.stream()
.map(list->{
System.out.println(list);
new CallAPI().make_call(list, access_token);
return "finished";
}).collect(Collectors.toList());
List<Future<String>> futures = es.invokeAll(tasks);
es.shutdown();
Then you have the futures, you can use them to check for exceptions, or if the task completed ok.
The following method shuts down an ExecutorService in two phases, first by calling shutdown to reject incoming tasks, and then calling shutdownNow, if necessary, to cancel any lingering tasks:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
}
boolean awaitTermination(long timeout, TimeUnit unit)
Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
To terminate the ExecutorService when all tasks are finished, just call es.shutdown(). Your own thread will continue the execution, while the task-threads will process all queued tasks.
From Java Doc:
shutdown
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that.
You need awaitTermination, when you want to block your own thread.

Find out if threads are still running in threadPool

I have following part of code:
protected ExecutorService parallelExecutor = Executors.newCachedThreadPool();
protected ExecutorService serialExecutor = Executors.newSingleThreadExecutor();
List<?> parallelCommands = new ArrayList<?>();
List<?> serialCommands = new ArrayList<?>();
List<Future<Boolean>> results = null;
LocalDateTime timed = LocalDateTime.now().plusSeconds(60);
results = parallelExecutor.invokeAll(parallelCommands);
results.addAll(serialExecutor.invokeAll(serialCommands));
Now I would like to check if both executors finish their job within a timeout or not:
while (LocalDateTime.now().isBefore(timed)) {
\\ here I need to check if meanwhile my threads finished
\\ if yes, break;}
How can I verify if the executors finished their job?
JDK documentation:
void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // Disable new tasks from being submitted
try {
// Wait a while for existing tasks to terminate
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow(); // Cancel currently executing tasks
// Wait a while for tasks to respond to being cancelled
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (InterruptedException ie) {
// (Re-)Cancel if current thread also interrupted
pool.shutdownNow();
// Preserve interrupt status
Thread.currentThread().interrupt();
}
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html#awaitTermination-long-java.util.concurrent.TimeUnit-
Use a counter to keep track of each task that finishes. You can decrement and check by modifying tasks added to your task list or by using a CompletableFuture.
List<Callable<?>> tasks = ...
ExecutorService executor = ...
// Might want to add the size of your other task list as well
AtomicInteger counter = new AtomicInteger(tasks.size());
for (Callable<?> callable : tasks) {
results.add(executor.submit(new Callable() {
callable.call();
int value = counter.decrementAndGet();
if (value == 0) {
synchronized (this) {
OuterClass.this.notify();
}
}
});
}
long timed = System.currentTimeMillis();
synchronized (this) {
long timeLeft;
// Or however many millis your timeout is
while ((timeLeft = 60_000 - System.currentTimeMillis() - timed) > 0) {
this.wait(timeLeft);
}
}
What you want to do is wait until you run out of time on your main thread, while your tasks are executed by the executor. If a task finishes and it realizes that there are no tasks that haven't finished, it tells the waiting thread to continue. I use notify() instead of notifyAll() because no other threads should be waiting for this object except the main thread, but if you do have other threads, use the latter option.

Java main process suspended because of exceptions thrown from threads

The main process:
int cpus = Runtime.getRuntime().availableProcessors();
ExecutorService executor = Executors.newFixedThreadPool(cpus);
List<Callable<Object>> todo = new ArrayList<Callable<Object>>(lines.size());
for (int r = 0; r < lines.size(); r++) {
String filename = r + 1 + "";
todo.add(Executors.callable(new AppConsole(filename, lines.get(r))));
}
List<Future<Object>> answers = executor.invokeAll(todo);
The AppConsole class implements Runnable and the overriden run method is as follows:
public void run() {
try{
} catch (SecurityException exception) {
exception.printStackTrace();
} catch (FileNotFoundException exception) {
exception.printStackTrace();
} catch (IOException exception) {
exception.printStackTrace();
} catch (SAXException exception) {
exception.printStackTrace();
} catch (Exception exception) {
exception.printStackTrace();
} finally {
if (output != null) {
output.close();
}
}
}
}
The main process is suspended and cannot finish because of a connection timeout exception thrown from one of the threads. Now I can see the cpu usage drops to 0% and the memory consumption keeps at the same level when it got suspended.
Could someone please help me solve this problem? At least, help me make the main process finish?
Throwing an exception frees up the tasks and the main thread. The ExecutorService treats an Exception throw much like another return value and doesn't have a problem handling it.
The main thread will only block waiting for one of your tasks to complete. I would look at the tasks/threads which are still active to see what they are doing e.g. perhaps they haven't timed out yet.
you could use the alternative version of invokeAll that takes an explicit timeout value :
http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html
invokeAll(Collection<? extends Callable<T>> tasks,
long timeout,
TimeUnit unit)
this way you can force all of your tasks to timeout after, say, 30 seconds. Then you can inspect the Futures returned to see which have completed.
You just need to add:
executor.shutdown();
This waits when all tasks will be completed and shutdown all threads, application will exit after that.
Please see javadoc for newFixedThreadPool:
Creates a thread pool that reuses a fixed number of threads operating
off a shared unbounded queue. At any point, at most nThreads threads
will be active processing tasks. If additional tasks are submitted
when all threads are active, they will wait in the queue until a
thread is available. If any thread terminates due to a failure during
execution prior to shutdown, a new one will take its place if needed
to execute subsequent tasks. The threads in the pool will exist until
it is explicitly shutdown.

Categories

Resources