Reputation: 2451
I am using Executors for thread pool, and submitting tasks. Can executorService.shutdownNow will shutdown all the tasks even though some of them may be blocked on I/O calls to database or Socket?
Upvotes: 2
Views: 1897
Reputation: 1066
When its not possible to handle interrupts (java.io), non-standard shutdown logic is required.
My solution to encapsulating this problem combines the examples 'TrackingExecutorService' and 'SocketUsingTask' from 'Java Concurrency In Practice'.
public interface Shutdownable {
public void shutdown();
}
public class ShutdowningExecutor extends ThreadPoolExecutor{
private final Set runningShutdownables
= Collections.synchronizedSet(new HashSet());
@Override
protected RunnableFuture newTaskFor(final Callable callable){
if (callable instanceof Shutdownable) {
runningShutdownables.add((Shutdownable) callable);
return super.newTaskFor(new Callable(){
@Override
public T call() throws Exception {
T t = callable.call();
runningShutdownables.remove((Shutdownable) callable);
return t;
}
});
} else
return super.newTaskFor(callable);
}
public void shutdownAll() {
for(Shutdownable shutdownable : runningShutdownables) {
shutdownable.shutdown();
}
}
@Override
public List shutdownNow(){
shutdownAll();
return super.shutdownNow();
}
}
public abstract class ShutdownableViaCloseable implements Shutdownable{
private Closeable closeable;
protected synchronized void setCloseable(Closeable c) { closeable = c; }
public synchronized void shutdown() {
try {
if (closeable != null)
closeable.close();
} catch (IOException ignored) { }
}
}
public class MySocketTask extends ShutdownableViaCloseable implements Callable {
public MySocketTask(Socket s) {
setCloseable(s);
//constructor stuff
}
public Void call() {
try (Socket socket = this.socket) {
while(!socket.isClosed) {
//do stuff
}
}
}
}
Upvotes: 1
Reputation: 1803
It depends on whether your tasks are well written!
The documentation says: "The shutdown() method will allow previously submitted tasks to execute before terminating, while the shutdownNow() method prevents waiting tasks from starting and attempts to stop currently executing tasks."
However, Java doesn't kill threads "out of thin air". It tries to interrupt them. A good task will throw an InterruptException
of some sort when shtudownNow tries to interrupt them, and end gracefully. You mention socket communication- most decent clients' blocking methods will throw an interrupted exception if they are interrupted.
An example of a bad task might be (rather obviously) to run a thread with while(true) { readChunk(); if(endOfChunks) { break;} }
. This offers no graceful interrupt check! It's the old rule not to use while loops to wait, but to wait()
using syncronized
on a 'blocker' object that can be interrupted.
Upvotes: 4
Reputation: 1747
Simply put: you cannot rely on that. The ExecutorService
simply interrupts the running tasks; it is up to the implementation of the tasks if they really cancel their endeavor. Some I/O can (and will) be interrupted, especially the java.nio
stuff, but the java.io
is most likely not interrupted. See What does java.lang.Thread.interrupt() do? for a bit more explanation.
Upvotes: 0
Reputation: 49412
No, there is no guarantee. If you see the API doc for ExecutorService#shutdownNow. It says,
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks.
If you want to block until all tasks have completed execution after a shutdown request,use ExecutorService#awaitTermination.
Upvotes: 1