My code:
ScheduledServiceExecutor service = Executors.newSingleThreadScheduledExecutor();
ScheduledFuture future = service.scheduleWithFixedDelay(
runnable, 1, 1, TimeUnit.MILLISECONDS
);
// ...
// now it's time to shut it all down
future.cancel(true);
service.shutdown();
Am I right here? Maybe I should do:
service.shutdown();
future.cancel(true);
What do you think?
In this case, you only need the call to shutdown().
There are two options in the ScheduledThreadPoolExecutor, which is what is being created behind the scenes here. getExecuteExistingDelayedTasksAfterShutdownPolicy() defaults to true and getContinueExecutingPeriodicTasksAfterShutdownPolicy() defaults to false. So, simply shutting down the service will cause periodic tasks to be canceled, but any delayed tasks will still be executed. Since the task in question is a periodic task, it will be canceled upon shutdown.
My personal opinion is that it's better to call the .cancel(true) manually before shutdown. While operationally this has no different effect, I think it's good for programmers who may not know the options on the executor to see that the periodic task is meant to be canceled upon shutdown. This also means that if anyone ever comes in and changes the executor to one which doesn't cancel upon shutdown, this task will still be canceled. So really, I think the main benefit here is clarity of code.
Related
In essence, does calling the cancel() method in the ScheduledFuture<> returned by the ScheduledThreadPoolExecutor.scheduleAtFixedRate cancel all the future executions that may be queued in the ScheduledThreadPoolExecutor's work queue? Does the returned ScheduledFuture represent all possible future executions of that task? Or does it simply cancel the next scheduled execution, but may execute another execution immediately after?
does calling the cancel() method in the ScheduledFuture<> returned by the ScheduledThreadPoolExecutor.scheduleAtFixedRate cancel all the future executions that may be queued in the ScheduledThreadPoolExecutor's work queue?
I think this is a great question given that you're asking about this in the context of a ScheduledThreadPoolExecutor. The ScheduledThreadPoolExecutor docs indicate that when a task is cancelled, it may not be automatically removed from the queue, read the following.
When a submitted task is cancelled before it is run, execution is suppressed. By default, such a cancelled task is not automatically removed from the work queue until its delay elapses. While this enables further inspection and monitoring, it may also cause unbounded retention of cancelled tasks. To avoid this, set setRemoveOnCancelPolicy(boolean) to true, which causes tasks to be immediately removed from the work queue at time of cancellation.
My code is as follows:
public Future<String> getFuture() {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<String> future = executorService.submit(() -> {
//do something
return "test string";
});
executorService.shutDown(); // is this correct?
return future;
}
I am calling this service from other class to get the future:
Future<String> future = getFuture();
String result = future.get();
future.cancel(true); // will this assure that there wont be any thread leak?
Now out of executorService.shutDown() and future.cancel(true) which will assure that there wont be thread leaks?
Note that after calling future.cancel(true) when I check currently running threads in the result of Thread.getAllStackTraces() I can still find the thread where future executed.
You are asking the wrong question!
There is no point in creating a service within a method to then throw it away right there.
Creating that service instance doesn't come for free. The whole idea of this abstraction is to ensure to make efficient usage of infrastructure elements!
In other words: step back and rework your design; so that this service becomes a field of some class for example! And yes, that might turn out to be complicated. But most likely, spending time in that corner will pay out much more long term - compared to continuing the approach shown in your question.
It is a bad idea to create an executor then throw it away in each method call.
Now out of executorService.shutDown() and future.cancel(true) which will assure that there wont be thread leaks?
none of them.
executorService.shutdown() will just keep running the current tasks and reject new submitted tasks.
future.cancel(true) will interrupt the corresponding task if it is currently running (but it is your responsability to check if the task was interrupted and finish the execution of the task as soon as possible)
Note that after calling future.cancel(true) when I check currently running threads in the result of Thread.getAllStackTraces() I can still find the thread where future executed.
as I mentioned before, future.cancel(true) doesn't stop the thread. it only sends an interruption.
According to documentation, when shutdown() is invoked, any tasks that were already submitted (I assume via submit() or execute) will be executed. When shutdownNow() is invoked, the executor will halt all tasks waiting to be processed, as well as attempt to stop actively executing tasks.
What I would like to clarify is the exact meaning of "waiting to be processed." For example, say I have an executor, and I call execute() on some number of Runnable objects (assume all of these objects effectively ignore interruptions). I know that if I now call shutdown, all of these objects will finish executing, regardless.
However, if I call shutdownNow at this point, will it have the same effect as calling shutdown? Or are some of the objects not executed? In other words, if I want an executor to exit as fast as possible, is my best option always to call shutdownNow(), even when the Runnables passed to the executor all effectively ignore interruptions?
Let's say you have this fabulous Runnable that is not interruptible for 10 seconds once it's started:
Runnable r = new Runnable() {
#Override
public void run() {
long endAt = System.currentTimeMillis() + 10000;
while (System.currentTimeMillis() < endAt);
}
};
And you have an executor with just 1 thread and you schedule the runnable 10 times:
ExecutorService executor = Executors.newFixedThreadPool(1);
for (int i = 0; i < 10; i++)
executor.execute(r);
And now you decide to call shutdown:
The executor continues for the full 10 x 10 seconds and everything scheduled will be executed. The tasks don't see that you're shutting down their executor. shutdown can be used if you want a "short lived" executor just for a few tasks. You can immediately call shutdown and it will get cleaned up later.
Alternatively shutdownNow():
Takes 10 seconds. The already running task is attempted to be interrupted, but that obviously has no effect so it continues to run. The other 9 tasks that were still waiting in the queue are "cancelled" and returned to you as List so you could do something with them, like schedule them later. Could also take 0 seconds if the first task is not yet started. You'd get all tasks back. The method is used whenever you want to abort an entire executor.
What I would like to clarify is the exact meaning of "waiting to be processed".
It means all tasks whose run() method has not yet been called (by the executor).
If I call shutdownNow at this point, will it have the same effect as calling shutdown?
No.
Or is it possible that some of the objects will not be executed?
That is correct.
In other words, if I want an executor to exit as fast as possible, is my best option always to call shutdownNow(), even when the Runnables passed to the executor all effectively ignore interruptions?
That is correct.
Better still, recode the Runnables to pay attention to interrupts ... or put a timeout on the shutdown ...
The API for shutdownNow method says that :
There are no guarantees beyond best-effort attempts to stop processing
actively executing tasks. For example, typical implementations will
cancel via Thread.interrupt(), so any task that fails to respond to
interrupts may never terminate.
source
Long story short: I have a collection of Future objects. Some of them are already in progress, some are not. I iterate the collection and call future.cancel(false) which, according to the documentation, should cancel all Futures that are not currently running but should allow all the others to complete.
My question is: How do I know when a particular Future is completed after I have called future.cancel(false)? future.isDone() always returns true because cancel() was indeed called before that and future.get() always throws a CancellationException even though the Future is still running.
Any suggestions?
Since Future models the future result of a pending computation, and since that result is not forthcoming from a canceled future, it is reasonable that Future gives you no way to find out when the computation whose result has been disposed of will complete. In other words, you'd need another paradigm to achieve your goal with that approach.
If your wish is to wait for all the submitted tasks to complete, the closest thing which is directly supported by the Executor Service API is to shut down the entire executor service and wait for its termination.
If the above does not fit your solution, then I don't see a better approach than some custom solution, for example a custom implementation of Runnable, which does some housekeeping on the side so you can check when it has completed running.
You could add a flag to your Future implementation which will reflect the actual Future' state
given a Callable<Object> c:
futureTask1 = new FutureTask<Object>(c);
futureTask2 = new FutureTask<Void>(futureTask1, null);
executor.execute(futureTask2);
now if you want the result:
futureTask1.get()
if you're no longer interested in the result:
futureTask1.cancel(mayInterruptIfRunning)
if you want to wait to be sure the code in the callable is not (and will not become) running (whether never called, finished cancelling or finished producing the result):
futureTask2.get()
Even if cancelled before it started working, this waits for the executor to execute the scheduled task (which will to nothing if already cancelled), so this may unnecessariliy wait for other long-running tasks to complete. YMMV
I have a background task that I run using the ScheduledThreadPoolExecutor with code like this.
executor.scheduleWithFixedDelay(new BackgroundSync(), 0, 15, TimeUnit.MINUTES);
BackgroundSync implements Runnable.
Sometimes from a user event I want the delayed event to run now and not when the 15 minute timer goes off.
Some requirements:
There should only be one "BackgroundSync" running at a time
Based off an user event I should be able to schedule a BackgroundSync immediately IF its not running already.
scheduleWithFixedDelay returns a ScheduledFuture. When calling it, store this somewhere and check if it exists if you want to do the immediate execution. Then you can cancel the scheduled future using the cancel method and schedule your runnable again for immediate execution.
Kabuko's solution is probably as good as you will get, but there is a snag.
The cancel() method returns true if the task was cancelled before it started, and false if the task has already run, or if it was previously cancelled. The problem is that if the task is currently running, cancel() will return true. Thus you need to implement some other mechanism to decide whether or not to resubmit the task.