Can't interrupt tasks of ExecutorService
Forced to find an alternative solution I completely removed the use of a thread pool and now implementing single Thread
s, stored in a Map
.
The interruption was, again, never happening so an AtomicBoolean
is now controlling the Thread's execution.
private AtomicBoolean stopped = new AtomicBoolean(false);
@Override
public void run() {
while (!stopped.get()) {
readUrl();
}
}
public void stopExecution() {
stopped.set(true);
}
It's a desperate move, but the only one that works so far.
You answered already with a valid workaround to avoid this issue but I will explain the cause. The fault is not with the ExecutorService
but with the thread's interrupt status being cleared silently by the network library.
As you and another commenter have found this could very well depend on the particular device you are using and its Android version.
As of Android 4.4 OkHttp
is used as the HttpUrlConnection
. There is a race condition between when each thread is interrupted and whether or not the InputStream
has been closed in older versions.
As a part of the close()
call this code is eventually executed:
public void throwIfReached() throws IOException {
if (Thread.interrupted()) {
throw new InterruptedIOException("thread interrupted");
}
if (hasDeadline && deadlineNanoTime - System.nanoTime() <= 0) {
throw new InterruptedIOException("deadline reached");
}
}
You can see based on the Thread.interrupted()
call it clears the interrupt status of the thread and never sets it again.
To make matters worse it looks like you can instead rely on the InterruptedIOException
but that is silently handled internally when closing the stream so you have no chance to handle it.
Your code sample worked for me when using a more recent version of OkHttp
. In later versions it looks like more care was taken to keep the interrupt status and it actually works as expected.
However, based on some searching it looks like historically interrupts do not play nicely with OkHttp
and to stop a request they recommend Call.cancel()
where possible instead.