Java: How do I catch InterruptedException on a thread, when interrupted by another thread?

徘徊边缘 提交于 2019-12-05 07:42:52
Cratylus

So, here is the question, within the connection thread, how do I catch the InterruptedException?

You can not. Since if your thread is blocked on a read I/O operation it can not be interrupted. This is because the interrupt just sets a flag to indicate that the thread has been interrupted. But if your thread has been blocked for I/O it will not see the flag.
The proper way for this is to close the underlying socket (that the thread is blocked to), then catch the exception and propagate it up.
So since your connection threads extend Thread do the following:

@Override  
public void interrupt(){  
   try{  
      socket.close();  
   }  
   finally{  
     super.interrupt();  
   }  
}   

This way it is possible to interrupt a thread blocked on the I/O.

Then in your run method do:

@Override  
public void run(){  

    while(!Thread.currentThread().isInterrupted()){    
       //Do your work

    }  
}    

So in your case don't try to catch an InterruptedException. You can not interrupt the thread blocked on I/O. Just check if your thread has been interrupted and facilitate the interruption by closing the stream.

When you call Thread.interrupt() on some thread, what happens is that 'interruption' flag is set for that thread. Some methods do check this flag (by Thread.interrupted() or Thread.isInterrupted()) and throw InterruptedException, but usually only methods that can block do that. So there is no guarantee that InterruptedException will ever be thrown in interrupted thread. If you don't call any method that throws InterruptedException, there is no point in catching that exception, since it will not be thrown at all. However you can always check if your thread was interrupted by calling Thread.isInterrupted().

the problem it is with blocking.

Hoverer, try this code, maybe it will help you:

try{
 yourObject.read();
}catch(InterruptedException ie){
// interrupted by other thread
}
catch(Exception ex){
// io or some other exception happent
}

your read method, should check if there is available buytes at socket for eg, if there are than read it, othervise go to speel mode. When is sleeping than is available the wake up (InterruptedException) at pur socket read ( whatever read have you) it will be blocked. Some API has a value to max waiting, eg 5 sec 60 sec, if nothing o read than it will be next code executed.

class MyReadingObject
{
   public read() throws InterruptedException{
      while(shouldIread){
        if(socket.available() > 0){
           byte[] buff = new byte[socket.avaialble()]
           socket.read(buff);
           return;
        }
        else{
           Thread.currentThread.sleep(whateverMilliseconds);
        } 
     }
  }
}

something like that, but with error handling and some design patterns

Sanjay T. Sharma

Calling interrupt() on a thread doesn't stop it, it just switches on the interrupt flag. It's the responsibility of the code to handle the change in the interrupt status of the thread in consideration and act accordingly. If you are performing a blocking operation in that thread, you are pretty much SOL because your thread is "blocking" on the read. Have a look at the answer which I posted here. So basically, unless you are looping over stuff or periodically checking some flags inside that thread, you have no way of breaking out without closing sockets or stuff like that.

One solution here is to "explicitly" expose the underlying connection object and call close() on it, forcing it to throw some sort of exception, which can be then handled in the threaded code. Something like:

class MyAction extends Thread implements Disposable {

  public void doStuff() {
    try {
      byte[] data = this.connection.readFully();
  } catch (InterruptedException e) {
    // possibly interrupted by forceful connection close    
  }

  @Override
  public void dispose() {
    this.connection.close();
  }
}

// Elsewhere in code
MyAction action = conMap.get("something");
action.dispose();

Use a try-catch like so:

try {
    //code
} catch ( InterruptedException e) {
    //interrupted
}

I think that should do the trick, you could also keep a boolean variable on whether to exit, so they would check that variable, if it's true, stop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!