78

In the context of Java, I create a new thread to read network input when open a GUI window, and when i close the window, i want to release the socket resource and terminate the thread immediately. Now i am using setSoTimeout method, but i don't want to wait the timeout exception. Could anybody give some suggestion? Thanks!

dingx
  • 1,533
  • 1
  • 18
  • 35

2 Answers2

63

There are (potentially) three ways to do this:

  • Calling Socket.close() on the socket will close the associated InputStream and OutputStream objects, and cause any threads blocked in Socket or (associated) stream operations to be unblocked. According to the javadoc, operations on the socket itself will throw a SocketException.

  • Calling Thread.interrupt() will (under some circumstances that are not specified) interrupt a blocking I/O operation, causing it to throw an InterruptedIOException.

    Note the caveat. Apparently the "interrupt()" approach doesn't work on "most" modern Java platforms. (If someone else had the time and inclination, they could possible investigate the circumstances in which this approach works. However, the mere fact that the behavior is platform specific should be sufficient to say that you should only use it if you only need your application to work on a specific platform. At which point you can easily "try it" for yourself.)

  • A possible third way to do this is to call Socket.shutdownInput() and/or Socket.shutdownOutput(). The javadocs don't say explicitly what happens with read and/or write operations that are currently blocked, but it is not unreasonable to think that they will unblock and throw an exception. However, if the javadoc doesn't say what happens then the behavior should be assumed to be platform specific.

Stephen C
  • 669,072
  • 92
  • 771
  • 1,162
  • 2
    Please, under what circumstances will thread.interrupt() interrupt a blocking I/O operation? – dingx Dec 13 '10 at 17:15
  • 3
    Xu DXn - it is not documented. Some streams implement this, others don't. For the gory details, read the OpenJDK source code. The point I'm trying to make is that it may or may not work. – Stephen C May 30 '11 at 04:06
  • 1
    pretty sure most jvm implementations do _not_ support interruptible io operations. i think maybe the sun solaris jvm supported it at one point. – jtahlborn Dec 16 '11 at 01:45
  • 8
    As an addendum to this, because a lot of Java programmers these days are actually working on Android, it should be noted that some versions of Android have a bug in Socket.close () that stops this technique working. Calling Socket.shutdownInput() beforehand does work, however. – Jules Nov 15 '12 at 15:14
  • Can you clarify whether the existing blocking operation will throw SocketException, or whether only new operations on the socket will throw SocketException? – user239558 Jan 10 '13 at 15:06
  • @user239558 - No I can't clarify that. The javadoc is the definitive documentation. If it doesn't say, then the behaviour is not specified. – Stephen C Apr 23 '13 at 08:21
  • From JavaDoc: "Any thread currently blocked in an I/O operation upon this socket will throw a SocketException." – Neeme Praks Feb 19 '14 at 15:52
  • @NeemePraks - I already said that. See the last sentence of my Answer. What I am saying to "user239588" is that we cannot clarify the behaviour *beyond what the javadoc says* (!). I'm hinting that >>he<< should read the javadoc for himself. – Stephen C Feb 19 '14 at 22:41
  • @StephenC I guess the hint was so subtle that it was lost :-P – Neeme Praks Feb 20 '14 at 13:00
  • 1
    @StephenC There are *three* ways to do this. Shutting down the input will cause the read to unblock instantly and return an EOS condition. `ClosedByInterruptException` is for NIO [`InterruptibleChannel`](https://docs.oracle.com/javase/6/docs/api/java/nio/channels/InterruptibleChannel.html) only, not streams or `Sockets`. – user207421 Nov 21 '14 at 00:01
  • @EJP - Maybe, but the javadoc doesn't say that. Unlike the javadoc for close() that says **explicitly** that blocked reads / writes will be unblocked. – Stephen C Nov 21 '14 at 00:06
  • @StephenC `shutdownInput()` ["places the input stream for this socket at "end of stream"](https://docs.oracle.com/javase/7/docs/api/java/net/Socket.html#shutdownInput()), and `read()` ["blocks until input data is available, the end of the stream is detected ..."](https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#read()) No 'maybe' about it. – user207421 Nov 21 '14 at 00:10
  • @EJP - That is not sufficiently specific for me. It doesn't say when the end of stream will be detected. There is sufficient wriggle room for an implementation of (say) `read()` to not "detect" the end of stream condition when it is caused by a local shutdown. (And besides, Java is probably dependent on the OS to implement this ...) – Stephen C Nov 21 '14 at 00:18
  • @StephenC Of course it is sufficiently specific, and of course Java is dependent on the OS, and of course it works. `read()` is *obliged* to detect EOS by the wording I quoted. There's nothing anywhere that suggests that end of stream can behave differently just because it is caused by a shutdown. – user207421 Nov 21 '14 at 01:33
  • @EJP - That is your opinion. I disagree. Let's leave it at that. – Stephen C Nov 21 '14 at 02:25
  • Late, but this is not my opinion, it is a series of valid inferences from known facts. If you can come up with a flaw in the logic or an implemnetation where it doesn't work please do so. I assert that you can't. – user207421 Oct 15 '16 at 23:55
  • @EJP - If you want to continue this, write your own answer and set out your case there. Clearly and with specificity. I'm not going to debate it in this comment stream any more – Stephen C Oct 16 '16 at 01:33
  • On MacOsx 10.13.3 java version "1.8.0_161" interrupting a thread gives me a IOException. – Felix Crazzolara Apr 01 '18 at 22:33
  • for me `shutdownInput()` does not unblock an existing `read()`, more specific a `readObject()` – SaPropper Nov 03 '20 at 12:45
19

I know this question is old but as nobody seems to have solved the "mystery" of Thread.interrupt() on "modern platforms" I did some research.

This is tested on Java 8 on Windows7 (64-bit) (but it will possibly be true for other platforms as well).

Calling Thread.interrupt() does not throw an InterruptedIOException What happens is that the InputStream.read() method returns with -1 and Thread.interrupted()-flag is set.

So the following could be considered a 'corrected' read() throwing InterruptedIOException:

static final int read(Socket socket, byte[] inData) 
    throws SocketTimeoutException, // if setSoTimeout() was set and read timed out
           InterruptedIOException, // if thread interrupted
           IOException             // other erors
{
    InputStream in = socket.getInputStream();

    int readBytes = in.read( inData, 0, inData.length);

    if  ( Thread.interrupted() )
    {
        throw new InterruptedIOException( "Thread interrupted during socket read");
    }

    return readBytes;
}
raudi
  • 1,699
  • 1
  • 16
  • 16
  • 1
    This answer deserves more up votes because Java's behavior when interrupted during Input/Output stream operations is not what many people expect. – Tom N. Apr 18 '17 at 16:37
  • 9
    This method works only if the InputStream provides data that can be read. Otherwise the code will be blocked by `in.read(...)` and the check if the thread has been interrupted will never be executed. – Robert Apr 18 '18 at 07:42