Java: Force stopping of ExecutorService threads
Solution 1
ExecutorService.shutdownNow()
will try to stop all the executing threads..
Here is a quote from javadoc
List<Runnable> shutdownNow()
Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so if any tasks mask or fail to respond to interrupts, they may never terminate.
Solution 2
Instant thread termination is never guaranteed, unless the thread checks periodically for isInterrupted() flag (or is waiting in interruptable method, i.e. which throws InterruptedException).
Consider implementing your worker threads in manner, when they check periodically for isInterrupted(). This may be something like that:
public void run() {
byte[] data;
do {
data = receiveDataChunk(timeout);
processData(data);
} while(!isInterrupted() && data != null);
}
Solution 3
Since downloading a torrent probably involves blocking IO operations, simply calling cancel()
/shutdownNow()
won't be enough, because blocking IO operations are not guaranteed to terminate when their respective threads are interrupted.
You also need to close the underlying sockets in order to cancel blocking IO, see How to terminate a thread blocking on socket IO operation instantly?.
Solution 4
ExecutorService.submit(...)
returns a Future<?>
that has a cancel()
method. You should keep track of these can call it when you want each task to stop.
Clark
Updated on October 16, 2020Comments
-
Clark over 3 years
My code:
String[] torrentFiles = new File("/root/torrents/").list(); if(torrentFiles.length == 0 || torrentFiles == null) { System.exit(0); } ex = Executors.newFixedThreadPool(3); for(String torrentFile : torrentFiles) { ex.submit(new DownloadTorrent("/root/torrents/" + torrentFile)); } ex.shutdown(); try { ex.awaitTermination(30, TimeUnit.MINUTES); } catch(InterruptedException ex1) { Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex1); }
But sometimes torrent downloading takes unknown time value and «
awaitTermination
» not works as I want. I need to stop all executed threads instantly after half an hour but as I know «awaitTermination
» just only useinterrupt()
method which works only in loops or waiting. So timeout not works if this moment happens. So, how to? -
pintxo almost 13 yearsIf he has not implemented a check on Thread.interrupted() in his implementation this will have no effect.
-
Akshay about 9 yearsI am also using shutdownNow() to stop all the other executing threads but I am able to stop a thread which is waiting for a service response. If I put the thread to sleep then it stops it immediately but in the pervious case it doesn't. Is there any specific reason for that?
-
Evgeni Sergeev about 8 yearsI'm not sure about the direct question, but instead of the
while
loop, a better pattern in such cases (where you can't tell from just looking at the code that it will terminate) is to say e.g.for (int retries = 0; retries < 1000; ++retries)
. Also, add a 10 ms wait between retries, or at leastyield()
. If it reaches 1000, log an error. (Instead of 1000 it should be some large number that is entirely unreasonable to expect if it behaved correctly.) -
skm almost 7 years@Akshay - yes there is reason for that happening. Thread.sleep() checks for interruption status and if the thread is already interrupted , it then throws InterruptedException. However in absence of such blocking thing happening, as mentioned in doc , There are no guarantees beyond best-effort attempts to stop processing actively executing tasks