Reputation:
I am really wondered how to interrupt a thread which is blocked by some I/O operation? The I/O is through a socket, and I do not want to close()
the socket.
I tried using Thread.interrupt()
to interrupt the thread, but without success.
Thread blocked by IO operation:
void run(){
byte[] data=new byte[1024];
in.read(data);//blocked!
}
Thread to interrupt the blocked thread (did not work):
void run(){
blockedThread.interrupt();//no success!
}
Upvotes: 3
Views: 1313
Reputation: 310957
Set a shortish read timeout on the socket and loop while you get SocketTimeoutException
, checking Thread.isInterrupted()
each time. Use Thread.interrupt()
to interrupt the thread.
Upvotes: 3
Reputation: 11250
I/O like the operations that are waiting for any monitor are not interruptible that is the reason that the InterruptedException
rutine is not needed by those cases, but according to Java 7 Documentation
the I/O classes that belong to nio
package can respond to any attempt to be interruted throwing one of the stream Interruption exception one of this is ClosedByInterruptionException
and it parent class AsynchronousCloseException
.
But in case that you want to close the excution thead, instead of closing the stream, you could consider make use of FutureTask
that provide the way to cancel.
Upvotes: 1
Reputation: 6193
Take a look at this blog post, especially Solution 4 – NIO with Buffering.
In short: For regular files you have to use NIO
, use a Channel
that extends AbstractInterruptableChannel
, eg. FileChannel
.
When using sockets use Socket#close()
to interrupt/close.
According to the javadocs:
Any thread currently blocked in an I/O operation upon this socket will throw a SocketException.
BUT:
There is another way around the problem: use asynchronous IO with NIO
, take a look at here.
The problem with asynchronous IO is, that it is really complex to handle(compared to blocking IO), since you will not relay on streams anymore, but buffers.
Upvotes: 1
Reputation: 15240
If you absolutely can't/don't want to close the socket using the normal java Socket
class, you can use a java.nio.SocketChannel to work with the socket.
SocketChannel
implements InterruptibleChannel which can be closed by interrupting the thread that waits on I/O on the socket. In this case the blocked read will throw a ClosedByInterruptException
Upvotes: 3
Reputation: 172458
You can add a method like this as any blocking IO operation will throw an IOException:-
public void close() throws IOException {
this.socket.close();
}
From the javadoc:-
Closes this socket. Any thread currently blocked in accept() will throw a SocketException.
Upvotes: 2
Reputation: 41281
Note how there is no InterruptedException
declared to be thrown:
read
public int read(byte[] b) throws IOException
Reads some number of bytes from the input stream and stores them into the buffer array b. The number of bytes actually read is returned as an integer. This method blocks until input data is available, end of file is detected, or an exception is thrown.
Some read methods will respond to an external interrupt via Thread#interrupt()
, either closing the stream or throwing an exception.
You can't otherwise stop this thread without somehow closing or feeding the stream from another thread, or by killing the thread with Thread#stop()
. This last method is only a last resort and shouldn't be used for assorted reasons.
Upvotes: 1
Reputation: 53694
Unfortunately, the sun java impl on most platforms does not handle io interruption via thread interrupt (i believe you can get this with some of the nio stuff, unsure). however, i believe if the thread is blocked reading from a socket, and you have a handle to that socket, you can asynchronously close the socket from another thread (which will interrupt the blocked thread).
Upvotes: 1