ScheduledFuture.get() is still blocked after Executor shutdown - java

I want to run some periodic task in background and I want to do it right.
So I schedule my task with ScheduledExecutorService.scheduleWithFixedDelay(..) and call ScheduledFuture.get() on the separate thread to control the life of the task, catch uncaught exceptions from it and get notified if the task is cancelled.
The problem is that if ScheduledExecutorService.shutdown() is called while the task is executing, than ScheduledFuture does not get notified and its get() method stays blocked forever.
And here comes the simple code to illustrate the problem:
public final class SomeService {
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
private final SomePeriodicTask task = new SomePeriodicTask();
private ScheduledFuture<?> future;
public void start() {
future = executor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.SECONDS);
final Runnable watchdog = new Runnable() {
#Override
public void run() {
try {
future.get();
} catch (CancellationException ex) {
System.out.println("I am cancelled");
} catch (InterruptedException e) {
System.out.println("I am interrupted");
} catch (ExecutionException e) {
System.out.println("I have an exception");
}
System.out.println("Watchdog thread is exiting");
}
};
new Thread(watchdog).start();
}
public void shutdownAndWait() {
System.out.println("Shutdown requested");
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (InterruptedException e) { //BTW When and why could this happen?
System.out.println("Waiting for shutdown was interrupted");
}
System.out.println("Executor is shutdown " + executor.isShutdown());
}
}
First, simple task which returns quickly
final class SomePeriodicTask implements Runnable {
#Override
public void run() {
System.out.print("I am just doing my job...");
System.out.println("done");
}
}
If we run it like this
public static void main(String[] args) throws InterruptedException {
SomeService service = new SomeService();
service.start();
Thread.sleep(3000);
service.shutdownAndWait();
System.out.println("Future is cancelled " + service.future.isCancelled());
System.out.println("Future is done " + service.future.isDone());
}
then the output is
I am just doing my job...done
I am just doing my job...done
I am just doing my job...done
Shutdown requested
I am cancelled
Watchdog thread is exiting
Executor is shutdown true
Future is cancelled true
Future is done true
totally as expected.
But if we modify the task to simulate some heavy job
final class SomePeriodicTask implements Runnable{
#Override
public void run() {
System.out.print("I am just doing my job...");
try {
Thread.sleep(1500); //Heavy job. You can change it to 5000 to be sure
} catch (InterruptedException e) {
System.out.println("Task was interrupted");
}
System.out.println("done");
}
}
so that the call to shutdown() happens while the task is executing... then the output is
I am just doing my job...done
I am just doing my job...Shutdown requested
done
Executor is shutdown true
Future is cancelled false
Future is done false
So what happened here... Executor is shutting down, as expected. It lets the current task to finish its job, as expected. We see that executor did finish shutting down, but our ScheduledFuture did not get cancelled and its get() method is still blocked and the watchdog thread prevents JVM from exiting and hangs forever.
Of course there are workarounds. For example I can call future.cancel(false) manually before shutdown or make watchdog a daemon thread or even try to schedule shutdown of Executor by himself so that it does not overlap with running task... But all of above have drawbacks and when code will get more complicated things can go sideways.
And anyway, I am seeking for your expert opinion because I will have no peace until I understand why it doesn't behave like it should. If it is a bug in jdk it must be reported. If I misunderstand something and my code is wrong, I must know it...
Thanks in advance

The first thing to understand is that for a periodic task, a normal completion does not turn the state of the Future to done as it expects to be rescheduled and possibly rerun.
This interferes with the semantics of Executor.shutdown; it will cancel all pending tasks but let the currently running tasks complete. So your currently running task completes normally and doesn’t set its state to done as it never does, but isn’t rescheduled because the executor has been shut down.
Even if you use shutdownNow it will interrupt the currently running tasks but not cancel them and since your task catches the InterruptedException and completes earlier but normally, there will be no state transition to done.
The best place to add the desired behavior of cancelling even tasks that completed normally upon shutdown is the Executor implementation; just change the line
private final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
to
private final ScheduledExecutorService executor = new ScheduledThreadPoolExecutor(1) {
#Override
protected void afterExecute(Runnable r, Throwable t) {
if(t==null && isShutdown() && r instanceof RunnableScheduledFuture<?>)
{
RunnableScheduledFuture<?> rsf = (RunnableScheduledFuture<?>)r;
if(rsf.isPeriodic()) rsf.cancel(false);
}
};
};

Related

How to end a thread in executor service if thread takes too long?

Sample executor service
static class MyRunnable implements Runnable {
private String serverName;
public MyRunnable(String serverName) {
super();
this.serverName = serverName;
}
#Override
public void run() {
...
conn = new ch.ethz.ssh2.Connection(serverName);
conn.connect();
boolean isAuthenticated = conn.authenticateWithPassword(user, pass);
logger.info("Connecting to " + server);
if (isAuthenticated == false) {
logger.info(server + " Please check credentials");
}
sess = conn.openSession();
...
}
}
public static void main(String[] args) {
List<String> serverList = ...;
ExecutorService executor = Executors.newFixedThreadPool(20);
for (String serverName : serverList) {
MyRunnable r = new MyRunnable(serverName);
executor.execute(r);
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.HOURS);
}
Right here is a sample code of my executor service. But with this logic when I meet a server that fails to connect or takes too long to connect it creates a a hang time within my application. I want to end/kill the thread if it takes longer than x amount of time to connect. How can I terminate the thread task if it does not connect to server within 2 seconds.
Attempt
ThreadPoolExecutor executor = new ThreadPoolExecutor(
10, 25, 500, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<>(1));
I added the following code but apparently it does not end the thread if it takes longer than 2000 milliseconds.
Attempt 2
Future<?> future = executor.submit( new task));
try {
future.get(2000, TimeUnit.MILLISECONDS); // This waits timeout seconds; returns null
}
catch(TimeoutException e) {
future.cancel(true);
// System.out.println(server + "name");
}
How can I terminate the thread task if it does not connect to server within 2 seconds.
This is difficult thing to do typically because even if you interrupt the thread (like the other answers mention) there's no guarantee that the thread will stop. Interrupt just sets a flag on the thread and it's up to the code to detect the status and stop. This means that a ton of threads may be in the background waiting for the connects.
In your case however you are using the ch.ethz.ssh2.Connection.connect() method. Turns out there is a connect method that takes a timeout. I think you want the following:
// try to connect for 2 seconds
conn.connect(null, 2000, 0);
To quote from the connect method javadocs:
In case of a timeout (either connectTimeout or kexTimeout) a SocketTimeoutException is thrown.
You have to do awaitTermination() first, then check the return value, and then do shutdownNow(). shutdown() does not guarantee instant stoppage of the service, it just stops taking new jobs, and waits for all jobs to complete in order. shutdownNow() on the other hand, stops taking new jobs, actively attempts to stop all running tasks, and does not start any new one, returning a list of all waiting-to-execute jobs.
From JavaDocs :
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();
}
}
You can always call future.get(timeout...)
It will return timeout exception if it did not finish yet... then you can call future.cancel().
As long as you deal with threads in Java the only safe way to stop the thread is to interrupt it. You can call shutdown() first and then wait. This method doesn't interrupt threads.
If it doesn't help then you call shutdownNow() which tries to cancel tasks by setting interrupted flag of each thread to true. In that case if threads are blocked/waiting then InterruptedException will be thrown. If you check interrupted flag somewhere inside your tasks then you are good too.
But if you have no other choice but to stop threads you still can do it. One possible solution of getting access to workers is to trace all created threads inside ThreadPoolExecutor with help of custom thread factory.
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class TestThreadPoolEx {
static class CustomThreadFactory implements ThreadFactory {
private List<Thread> threads = new ArrayList<>();
#Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
threads.add(t);
return t;
}
public List<Thread> getThreads() {
return threads;
}
public void stopThreads() {
for(Thread t : threads) {
if(t.isAlive()) {
try {
t.stop();
} catch (Exception e) {
//NOP
}
}
}
}
}
public static void main(String[] args) throws InterruptedException {
CustomThreadFactory factory = new CustomThreadFactory();
ExecutorService ex = Executors.newFixedThreadPool(1, factory);
ex.submit(() -> {
while(true);
});
ex.shutdown();
ex.awaitTermination(5, TimeUnit.SECONDS);
ex.shutdownNow();
ex.awaitTermination(5, TimeUnit.SECONDS);
factory.stopThreads();
}
}
This is sure unsafe but should fit your requirements. In this case it's able to stop while(true) loop. Cancelling tasks won't be able to do that.

Java - Close a thread with 'return' not working

I have the following code in a class which contains my main method
ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable formatConcentration = new formatConcentration(87);
executor.execute(formatConcentration);
System.out.println("Called an instance of formatConcentration");
while (!executor.isTerminated())
{
//stay Alive
Thread.sleep(1000);
System.out.println("Still alive");
}
System.out.println("Program successfully finished");
return;
This creates an instance of formatConcentration class. The code for which is the following (I've taken all of my functionality out for the sake of the example).
public class formatConcentration extends Thread{
private int numberOfNewRows;
formatConcentration(int rows)
{
this.numberOfNewRows = rows;
}
public void run() {
System.out.println("Running the Formatting Script");
final int numberOfNewRegistered = this.numberOfNewRows;
try
{
System.out.println("Finished formatting");
}//end of try
catch (Exception e1)
{
log.log(e1.toString());
log.closeLog() ;
System.exit(1) ;
}
System.out.println("Still Finished formatting");
return;
}
}
My problem is that once return is invoked it does not terminate the thread.
I have done quite a lot of looking around and as far as I can tell this should be fine but I would imagine that I'm overlooking something small and would appreciate fresh eyes on the problem.
Or if someone has a suggestion of how to kill the thread from inside the run(){} method I would greatly appreciate it (preferably not by setting a variable that I'll check in the main class but if that's how I have to do it so be it) as I know that once it reaches the return statement it's finished and no longer need any reference to variables created in run().
The output generated to the console is as follows:
Called an instance of formatConcentration
Running the Formatting Script
Finished formatting
Still Finished formatting
Still alive
Still alive
Still alive
Still alive
Still alive
etc.
You never shutdown the executor. From the Javadocs for isTerminated:
Returns true if all tasks have completed following shut down. Note that isTerminated is never true unless either shutdown or shutdownNow was called first.
As long as you don't shutdown the executor, you can submit new tasks to it for execution. isTerminated does not check the state of the submitted tasks, it checks the state of the ExecutorService itself.
ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable formatConcentration = new formatConcentration(87);
executor.execute(formatConcentration);
System.out.println("Called an instance of formatConcentration");
executor.shutdown();
while (!executor.isTerminated())
{
//stay Alive
Thread.sleep(1000);
System.out.println("Still alive");
}
System.out.println("Program successfully finished");
return;
Another simpler way to do it would be :
ExecutorService executor = Executors.newFixedThreadPool(1);
Runnable formatConcentration = new formatConcentration(87);
executor.execute(formatConcentration);
executor.shutdown();
try {
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Executor awaitTermination method substitutes your loop.
ExecutorService is mainly used to delegate your jobs to separte workers.
Using this only most of the Connection pooling libs have been created.
So this service will be initiated whenever your application is started and will be closed (manually) by your application's closing method.
In your program you should write a code to check the executor service's status,
Is any workers are currently working...
If no workers are in busy mode then just stop accepting any further tasks.
From javadocs see the sample shutdown code,
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();
}
}
Hope it will give some information to you.

future.cancel does not work

I have a nice and compact code, which does not work as I expected.
public class Test {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
for (;;) {
}
} finally {
System.out.println("FINALLY");
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(r);
try {
future.get(3, TimeUnit.SECONDS);
} catch (TimeoutException e) {
boolean c = future.cancel(true);
System.out.println("Timeout " + c);
} catch (InterruptedException | ExecutionException e) {
System.out.println("interrupted");
}
System.out.println("END");
}
}
The output is :
Timeout true
END
Question:
Why does not terminate the future.cancel(true) method the called Runnable?
After the program wrote the "END" to the output, the "r" Runnable is still running.
The problem is that your Runnable is not interruptible: task interruption is a collaborative process in Java and the cancelled code needs to check regularly if it's been cancelled, otherwise it won't respond to the interruption.
You can amend you code as follows and it should work as expected:
Runnable r = new Runnable() {
#Override public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {}
} finally {
System.out.println("FINALLY");
}
}
};
This is always a little bit misleading: The ExceutorService or even the underlying thread scheduler do not know anything about what the Runnable is doing. In your case they don't know that there is a unconditional loop.
All these methods (cancel, done, ...) are related to manage Threads in the Executor structure. cancel cancels the thread from the point of view of the Executor service.
The programmer must test if the Runnable was canceled and must terminate the run() method.
So in your case (if I remember well) something like this:
public class Test {
public static void main(String[] args) {
FutureTask r = new FutureTask () {
#Override
public void run() {
try {
for (;!isCancelled();) {
}
} finally {
System.out.println("FINALLY");
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(r);
try {
future.get(3, TimeUnit.SECONDS);
} catch (TimeoutException e) {
boolean c = future.cancel(true);
System.out.println("Timeout " + c);
} catch (InterruptedException | ExecutionException e) {
System.out.println("interrupted");
}
System.out.println("END");
}
}
When you cancel a Future whose Runnable has already begun, the interrupt method is called on the Thread that is running the Runnable. But that won't necessarily stop the thread. Indeed, if it's stuck in a tight loop, like the one you've got here, the Thread won't stop. In this case, the interrupt method just sets a flag called the "interrupt status", which tells the thread to stop when it can.
See the Javadoc for the interrupt method of Thread
Future.cancel() will cancel any queued task or will call Thread.interrupt() on your thread if already running.
You need to interrupt your code
It's your code's responsibility is to be ready for any interruptions. I'd go so far to say that whenever you have a long running task, that you insert some interrupt ready code like this:
while (... something long...) {
... do something long
if (Thread.interrupted()) {
... stop doing what I'm doing...
}
}
How to stop what I'm doing?
You have several options:
If your you are in Runnable.run() just return or break out of the loop and finish the method.
You may be in some other method deep in the code. It may make sense at that point for that method to throw InterruptedException so you would just do that (leaving the flag cleared).
But maybe deep in your code it doesn't make sense to throw InterruptedException. In that case you should throw some other exception, but before that mark your thread interrupted again so the code that catches knows that an interrupt was in progress. Here's an example:
private void someMethodDeepDown() {
while (.. long running task .. ) {
... do lots of work ...
if (Thread.interrupted()) {
// oh no! an interrupt!
Thread.currentThread().interrupt();
throw new SomeOtherException();
}
}
}
Now the exception can propagate an either terminate the thread or be caught, but the receiving code hopefully notices that an interrupt is in progress.

Future.get hangs when Callback catches InterruptedException

This code hangs. I understand that I call future.get() for the future that wasn't executed but I expect to see CancellationExcetpion or InterruptedException or some other exception on future.get() method. Am I wrong?
public class ExecutorTest {
static ExecutorService executorService = Executors.newFixedThreadPool(1);
public static void main(String[] args) throws Exception {
List<Future> futures = new ArrayList<Future>();
for (int i = 0; i < 10; i++) {
Future<Object> future = executorService.submit(new Callable<Object>() {
#Override
public Object call() throws Exception {
System.out.println("Start task");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Finish task");
return "anything";
}
});
futures.add(future);
}
new Thread() {
#Override
public void run() {
try {
Thread.sleep(10000);
System.out.println("Shutdown Now");
executorService.shutdownNow();
} catch (InterruptedException e) {
System.out.println("Interrupted Exception during shutdown");
}
}
}.start();
for(Future f : futures) {
System.out.println("-------------------------");
System.out.println("before sleep");
Thread.sleep(3000);
System.out.println("after sleep...");
try {
f.get();
} catch (Exception ex) {
System.out.println("exception during future.get");
}
System.out.println("after get!");
}
}
}
This is my output
Start task
-------------------------
before sleep
after sleep...
Finish task
after get!
-------------------------
Start task
before sleep
after sleep...
Finish task
Start task
after get!
-------------------------
before sleep
after sleep...
Finish task
Start task
after get!
-------------------------
before sleep
Shutdown Now
Finish task
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at ru.pp.ExecutorTest$1.call(ExecutorTest.java:28)
at java.util.concurrent.FutureTask.run(FutureTask.java:262)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:745)
after sleep...
after get!
-------------------------
before sleep
after sleep...
Java 8, Intellij
If I replace
System.out.println("Start task");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
with this
System.out.println("Start task");
Thread.sleep(3000);
then it doesn't hang
I'm frustrated...
When you invoke shutdownNow, the ExecutorService removes any scheduled, but not yet run, tasks and returns them to you as a List<Runnable>. These tasks have a corresponding Future which you already have a reference to. Since these tasks are never run, they never produce a result, ie. never complete. As such, the Future#get() for those tasks will never return.
If you wanted to, you could return run those tasks with
executorService.shutdownNow().forEach(r -> r.run());
and you would see your all Future#get() calls return.
You should probably only call Future#get() if you know the task is done/cancelled. Alternatively, give it a timeout.
When Thread_1 calls FutureTask#get then Thread_1#wait is called. Now to continue Thread_1 it should be notified by somebody. Notification is called ONLY when FutureTask is terminated (on FutureTask#set, FutureTask#setException or FutureTask#cancel). But in my case the FutureTask was never started because of shutdownNow (FutureTask was in state NEW). So it was never terminated and Thread_1#notify was never called.
To fix it I got all not started futures from #shutdownNow and didn't call FutureTask#get for them.
PS: Honestly FutureTask uses sun.misc.Unsafe#park #unpark methods instead of wait and notify.

Wait until child Thread Finishe, But Do Not Block Main Thread

I have been working on a java GUI application that on a particular action do some task. I have been doing this task using ExecutorService. Now the working with multiple threads works fine but the problem is that I do not want to block my GUI. User may want to cancel the current operation and may request for another one. But while using the ExecutorService, my main Thread gets blocked. I want to wait for my child threads to finish, invoked using ExecutorService, while still being able to work on GUI.
The updated code is:
ExecutorService child = Executors.newCachedThreadPool();
ExecutorService es = Executors.newCachedThreadPool();
#Action
public void doAction() {
/** Some Code goes here */
if(Condition){
if(!(es.isTerminated()||es.isShutdown())){
es.shutdownNow();
es = Executors.newCachedThreadPool();
}
es.execute(new Runnable() {
public void run() {
if(!(child.isTerminated()||child.isShutdown())){
child.shutdownNow();
child = Executors.newCachedThreadPool();
}
for(loopConditions){
child.execute(new Runnable() {
public void run() {
//Perform Some Task Here
}
});
}
child.shutdown();
try {
boolean finshed = child.awaitTermination(5, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
child.shutdownNow();
Logger.getLogger(MySearchView.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("All Child Threads finished Execution");
}
});
es.shutdown();
try {
boolean finshed = es.awaitTermination(5, TimeUnit.MINUTES);
} catch (InterruptedException ex) {
es.shutdownNow();
Logger.getLogger(MySearchView.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println("All Threads finished Execution");
/**
* Code that should run after all Threads finishes their Execution
*/
}
}
You're not using the Executors in the way they're intended. They are meant to be long-lived, created on application startup and torn down at the end. Don't use shutdownNow and awaitTermination during normal processing.
If you want to await the result of a task, call get() on the Future that was returned when you submitted it.
I would use a ScheduledExecutorService to shut itself down after 5 seconds.

Categories

Resources