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

Java:当一个线程被另一个线程中断时,如何捕获该线程上的InterruptedException?,java,multithreading,runnable,Java,Multithreading,Runnable,我正在开发一个多线程应用程序来连接到外部服务器——每个服务器都在不同的线程上——并将被阻止,直到有输入。其中每一个都扩展了Thread类。为了便于解释,让我们称这些为“连接线程” 所有这些连接线程都存储在并发hashmap中 然后,我允许RESTfulWeb服务方法调用来取消任何线程。(我使用的是Grizzly/Jersey,因此每个调用本身就是一个线程。) 我检索特定的连接线程(从hashmap)并对其调用interrupt()方法 因此,这里有一个问题,在连接线程中,如何捕获Interrup

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

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

然后,我允许RESTfulWeb服务方法调用来取消任何线程。(我使用的是Grizzly/Jersey,因此每个调用本身就是一个线程。)

我检索特定的连接线程(从hashmap)并对其调用interrupt()方法


因此,这里有一个问题,在连接线程中,如何捕获InterruptedException?(当连接线程被外部RESTful命令停止时,我想做一些事情。)

问题在于阻塞

Hover,试试这段代码,也许它会帮助你:

try{
 yourObject.read();
}catch(InterruptedException ie){
// interrupted by other thread
}
catch(Exception ex){
// io or some other exception happent
}
您的读取方法,应该检查插座上是否有可用的buytes,例如,如果有,则读取它,否则转到speel模式。当睡眠时间超过可用时间时,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);
        } 
     }
  }
}

诸如此类,但对于错误处理和一些设计模式,请使用如下的try-catch:

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

我认为这应该可以做到,你也可以保留一个布尔变量来决定是否退出,这样他们就会检查这个变量,如果它是真的,当你调用
Thread.interrupt()。有些方法确实会检查此标志(通过
Thread.interrupted()
Thread.isInterrupted()
)并抛出
InterruptedException
,但通常只有能够阻止的方法才能这样做。所以不能保证中断线程中会抛出
InterruptedException
。如果您不调用任何抛出
InterruptedException
的方法,那么捕获该异常就没有意义了,因为它根本不会被抛出。但是,您始终可以通过调用
thread.isInterrupted()
来检查线程是否被中断

因此,这里有一个问题,在连接线程中,我如何捕获 中断异常

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

@Override  
public void interrupt(){  
   try{  
      socket.close();  
   }  
   finally{  
     super.interrupt();  
   }  
}   
这样就可以中断I/O上阻塞的线程

然后在
运行
方法中执行以下操作:

@Override  
public void run(){  

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

    }  
}    
因此,在您的情况下,不要试图捕捉
中断异常。您不能中断I/O上阻塞的线程。只需检查您的线程是否已被中断,并通过关闭流来促进中断

在线程上调用
interrupt()
不会停止它,它只是打开中断标志。代码负责处理所考虑线程中断状态的变化,并相应地采取行动。如果您正在该线程中执行阻塞操作,那么您将非常满意,因为您的线程正在对读取进行“阻塞”。看看我贴的答案。所以,基本上,除非你是循环的东西或定期检查一些标志内的线程,你没有办法打破不关闭套接字或诸如此类的东西

这里的一个解决方案是“显式”公开底层连接对象,并对其调用
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();

好吧,好吧,当一个线程抛出InterruptedEx时。它将传播到启动异常引发线程的线程。您可以在该父线程处捕获IE。我刚刚做了一个实验来包围启动连接线程的代码,编译器警告不会抛出InterruptedException。此外,启动这些连接线程的父线程不会进入等待或睡眠状态,因此这意味着(或者至少我认为)它在启动所有这些子线程之后就不再存在了。“中断一个不活动的线程不需要有任何效果”@规格JSR-51我该把这个放在哪里?在run()方法中编译器会说代码不会抛出InterruptedException,也不会编译。我尝试过类似的方法,问题是“yourObject.read()”不会抛出InterruptedException。编译器将显示一个错误,代码中没有任何地方抛出该异常并拒绝编译。我看到我被否决了,我应该重新考虑我将在这里浪费多少时间。谢谢大家。帮帮忙,祝你好运!我不知道是谁投了你的反对票,但我投了你的赞成票,因为我认为不应该投反对票。我猜否决票是由于代码中的拼写错误/语法错误造成的?非常正确,您需要调用mycontroller.getReadingThread().interrupt();