Issue
My question is specific to android, but I suspect is applies to Java threads in general.
Let's say the run loop of a worker thread is doing this. Reading bytes from a network stream and doing stuff with each chunk read.
class MyWorker implements Runnable {
boolean _exitFlag;
Thread _thread;
void run()
{
HttpUrlConnection connection;
// connection establishment not shown for brevity
while(_exitFlag == false)
{
InputStream stream = connection.getInputStream();
int result;
try
{
result = stream.read(bytearray);
if (result == -1)
break;
processBytes(bytearray, result);
}
catch(IOException ioex)
{
break;
}
}
}
Now the other thread is ready to signal this thread to exit by calling another method on this class:
public void stop()
{
_exitFlag = true;
_thread.interrupt();
_thread.join();
}
It's my understanding that the _thread.interrupt
call will wake up the blocking io operation on the stream.read
call with an exception derived from IOException. That's assuming the thread is actually at that point in the code.
Let's say the stop
call was made immediately after the worker thread checked the _exitFlag==false
condition but before it got to the subsequent read
call?
Will the subsequent call to stream.read()
immediately throw an exception if the thread has a posted interrupt? Or will it continue to block and wait for the IO operation to complete? In other words, is this a race condition?
What is a good pattern for signaling a worker thread that may be in the middle of a long blocking io operation to exit?
Solution
They are separate things. The call to Thread.interrupt only sets a flag in the target Thread. It is up to that Thread to handle the call. If the Thread is sleeping then an InterruptedException will be thrown and it is up to the target Thread to handle the exception (or throw it again). However, if the target Thread is not in a state that throws InterruptedException (not sleeping and not joining) then it is up to the target Thread to be constantly checking for the signal via Thread.interrupted()
.
In your example, it is up to the thread reading the stream to check periodically if the interrupted
flag has been set or not.
In your code, I would check the flag using something like
result = stream.read(bytearray);
if (result == -1)
break;
processBytes(bytearray, result);
if (Thread.interrupted()) {
// We've been interrupted: no more crunching.
// handle the interruption here by throwing an Exception or returning.. or something else
}
Answered By - Alexandre Santos
Answer Checked By - Gilberto Lyons (JavaFixing Admin)