我正在开发一个多线程应用程序来连接外部服务器 - 每个都在不同的线程上 - 并且会被阻塞直到有输入。其中每个都扩展了Thread类。为了便于解释,我们称之为“连接线程”。
所有这些连接线程都存储在并发hashmap中。
然后,我允许RESTful Web服务方法调用取消任何线程。 (我正在使用Grizzly / Jersey,因此每次调用都是一个独立的线程。)
我检索特定的连接线程(来自hashmap)并在其上调用interrupt()方法。
所以,这是一个问题,在连接线程中,我如何捕获InterruptedException? (当外部RESTful命令停止连接线程时,我想做点什么。)
答案 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
}
我认为应该这样做,你也可以保留一个布尔变量是否退出,所以他们会检查那个变量,如果它是真的,停止