Richard Stokes
Richard Stokes

Reputation: 3552

Killing a thread in Java using Thread.interrupt

I have a thread running in my Swing chat application to listen indefinitely through a socket for datagrams. When I close this application, I have the following code execute:

listenThread.interrupt();
socket.close();

However, interrupt doesn't seem to be stopping the thread, as when the socket closes, the loop continues listening, and throws exceptions since the socket has been closed. How do I get the thread to exit properly so that I can close the socket safely?

Upvotes: 0

Views: 940

Answers (4)

JimmyB
JimmyB

Reputation: 12630

interrupt() cannot be used to interrupt an I/O operation such as socket reads or writes. To abort the I/O, closing the socket is the right way. After your thread receives the IOException it should check if it was interrupted in the meantime and then gracefully exit.

Example for the code in your I/O thread:

while( !Thread.currentThread().isInterrupted() ) {
  try {
    doRead();
  } catch ( IOException ioe ) {
    // Log exception or whatever
  }
}

Upvotes: 4

user296828
user296828

Reputation:

I'm going to assume you've implemented this the easy way and done:

 DatagramSocket s = new DatagramSocket( port );
 DatagramPacket p = new DatagramPacket( new byte[256], 256);
 s.receive( p );

Now, looking at the Javadoc, there's no way to get the DatagramSocket.receive() to throw an InterruptedException. Closing the socket is the only way to get it to stop listening.

A better implementation of this would have been to set a time out on the DatagramSocket using DatagramSocket.setSoTimeout( int ) to something small like 2 seconds, and then check if your server has been interrupted. So you'd end up with something like this for your server code ( doesn't handle exceptions ):

DatagramSocket s = new DatagramSocket( port );
s.setSoTimeout( 2000 ); // 2 second time out

while( running ){ // boolean running flag, check for interrupt here
    try{
        DatagramPacket p = new DatagramPacket( new byte[256], 256);
        s.receive( p );
        //do stuff
    } catch ( SocketTimeoutException e ){
        //timed out
    }
}//end while

Upvotes: 0

Martin James
Martin James

Reputation: 24907

If it's throwing an exception, catch it and exit the UDP read thread. Throwing an exception when the socket is closed from another thread is expected - make use of it!

Failing that, set the interrupted flag and make the UDP read() return by sending it a datagram on the local TCP stack from a socket in thread requesting the shutdown. UDP is a connectionless message service and is quite happy to receive a datagram from another thread on the same box. The datagram could contain a shutdown instruction, or you could check the isInterrupted flag after every read() return, just in case it's set.

Upvotes: 0

Alex Gitelman
Alex Gitelman

Reputation: 24732

interrupt() only notifies the thread about someone's intention to stop it. It's up to the thread to properly exit. If thread is waiting on the monitor it will receive InterruptedException, otherwise you can check isInterrupted() on the current thread. However, if it's waiting on IO you may be out of luck and your only choice is to wait for socket time out to expire. Then you will check if thread is interrupted and close the socket.

Upvotes: 1

Related Questions