Reputation: 97
I have an ExecutorService that runs a few threads.
What I am trying to accomplish is to execute, and then wait for all threads to terminate. To give you more background, every thread1
connects to a website.
This is what I came up with:
public static void terminateExecutor(ExecutorService taskExecutor) {
taskExecutor.shutdown();
try {
taskExecutor.awaitTermination(2, TimeUnit.SECONDS);
} catch (InterruptedException e) {
System.out.println("Some tasks were interrupted!"); //This gets printed
}
}
Now, strangely enough, the main thread that uses the ExecutorService terminates, but the thread1
s in it don't.
I noticed this because thread1
threw an error (the main thread at this point was already dead) telling me that it didn't find the URL specified (so I guess it's something related to connections).
Is it possible that awaitTermination
doesn't terminate the thread1
because its trying (and retrying it seems) to connect to an invalid link?
I cannot stop the thread1
in any other way (or at least to my knowledge I can't), because there isn't any kind of loop.
EDIT:
I get thread1
by creating a new class and feeding it to the executor.
for (....)
{
String urlToVisit = globalUrl + links.get(i);
Thread thread1 = new MagicalThread(urlToVisit, 2).getThread();
executor.execute(thread1);
}
terminateExecutor(executor.getExecutor());
Upvotes: 2
Views: 1337
Reputation: 96444
The executor uses interruption to let the threads know it's time to quit. If your tasks are using blocking I/O then they will be blocked and can't check the interrupt flag. There is no ability for the blocked task to respond to the interruption in the way that happens with sleep or wait, where interruption causes the threads to wake up and throw an InterruptedException.
If you set a timeout on the socket then, once the socket times out, the task can check for interruption. Also you can have the task respond to interrupt by closing the socket. See https://www.javaspecialists.eu/archive/Issue056.html
Be aware that implementing this in a threadpool is more involved than in the example given in the linked article. Nothing about the executor lets the pool call methods on a task besides run. One way to do it would be to put a reference to the socket in a ThreadLocal. Then you could make a ThreadFactory for the pool to use to subclass Thread with a method that overrides the interrupt method on the thread to get the socket from the ThreadLocal and close it.
Upvotes: 0
Reputation: 140524
When
taskExecutor.awaitTermination(2, TimeUnit.SECONDS);
returns, it doesn't guarantee that the ExecutorService
has terminated. Look at its return value:
[Returns] true if this executor terminated and false if the timeout elapsed before termination
You don't check this value, but I'll bet it's returning false if the thing you're running in the ExecutorService
is still running.
Upvotes: 0