Java:当被另一个线程中断时,如何在线程上捕获InterruptedException?

时间:2012-09-01 19:15:50

标签: java multithreading runnable

我正在开发一个多线程应用程序来连接外部服务器 - 每个都在不同的线程上 - 并且会被阻塞直到有输入。其中每个都扩展了Thread类。为了便于解释,我们称之为“连接线程”。

所有这些连接线程都存储在并发hashmap中。

然后,我允许RESTful Web服务方法调用取消任何线程。 (我正在使用Grizzly / Jersey,因此每次调用都是一个独立的线程。)

我检索特定的连接线程(来自hashmap)并在其上调用interrupt()方法。

所以,这是一个问题,在连接线程中,我如何捕获InterruptedException? (当外部RESTful命令停止连接线程时,我想做点什么。)

5 个答案:

答案 0 :(得分:9)

  

所以,这是一个问题,在连接线程中,我该如何捕获   InterruptedException?

你做不到。由于如果您的线程在读取I / O操作中被阻止,则它不能是interrupted。这是因为interrupt只是设置一个标志来指示线程已被中断。但是如果您的线程已被I / O阻止,它将看不到该标志 正确的方法是关闭底层套接字(线程被阻塞),然后捕获异常并将其传播。
因此,由于您的连接线程extend Thread执行以下操作:

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

这样就可以中断I / O上阻塞的线程。

然后在您的run方法中执行:

@Override  
public void run(){  

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

    }  
}    

因此,在您的情况下,请勿尝试catch InterruptedException。您无法中断I / O上阻塞的线程。只需检查您的线程是否已被中断,并通过关闭流来促进中断。

答案 1 :(得分:2)

阻塞的问题。

Hoverer,试试这段代码,也许它会对你有帮助:

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

你的阅读方法,应该检查插座上是否有可用的买入物,例如,如果有比阅读它,其他人去了拼写模式。当睡眠时间超过可用时,在pur套接字读取唤醒(InterruptedException)(无论读取什么)它将被阻止。某些API具有最大等待值,例如5秒60秒,如果没有读取,则会执行下一个代码。

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);
        } 
     }
  }
}

类似的东西,但有错误处理和一些设计模式

答案 2 :(得分:2)

当你在某个线程上调用Thread.interrupt()时,会发生的是为该线程设置'interruption'标志。有些方法检查此标志(Thread.interrupted()Thread.isInterrupted())并抛出InterruptedException,但通常只有可以阻止的方法执行此操作。因此无法保证InterruptedException将被抛出中断的线程。如果你没有调用抛出InterruptedException的任何方法,那么捕获该异常是没有意义的,因为它根本不会被抛出。但是,您始终可以通过调用Thread.isInterrupted()来检查您的线程是否被中断。

答案 3 :(得分:1)

在线程上调用interrupt()并不停止它,它只是打开中断标志。代码负责处理所考虑的线程的中断状态的变化并相应地采取行动。如果你在该线程中执行阻塞操作,那么你几乎是SOL,因为你的线程是"阻塞"在阅读。看看我发布的答案here。所以基本上,除非你循环覆盖东西或定期检查该线程中的一些标志,否则你无法在没有关闭套接字或类似东西的情况下爆发。

这里的一个解决方案是"明确"暴露底层连接对象并在其上调用close(),强制它抛出某种异常,然后可以在线程代码中处理。类似的东西:

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();

答案 4 :(得分:-1)

像这样使用try-catch:

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

我认为应该这样做,你也可以保留一个布尔变量是否退出,所以他们会检查那个变量,如果它是真的,停止