Java 调用interrupt()时线程未抛出InterruptedException
我正在开发一个通过网络读取和处理数据的应用程序。在测试程序的连接/断开逻辑时,我注意到我的使用者线程在达到关闭状态时没有关闭。下面是消费者类的精简版Java 调用interrupt()时线程未抛出InterruptedException,java,multithreading,interrupt,Java,Multithreading,Interrupt,我正在开发一个通过网络读取和处理数据的应用程序。在测试程序的连接/断开逻辑时,我注意到我的使用者线程在达到关闭状态时没有关闭。下面是消费者类的精简版 import java.io.InputStream; public class Consumer implements Runnable { private final InputStream input; public Consumer(InputStream input) { this.input = inpu
import java.io.InputStream;
public class Consumer implements Runnable
{
private final InputStream input;
public Consumer(InputStream input)
{
this.input = input;
}
@Override
public void run()
{
byte readBuffer[];
readBuffer = new byte[1];
int goodData;
try
{
while(input.available() > 0)
{
goodData = input.read(readBuffer);
while (goodData > 0 )
{
System.out.println(readBuffer[0]);
if ( readBuffer[0] == 27 )
{
System.out.println("Consumer: found closing byte and closing thread "+Thread.currentThread().getName());
//this is the last packet, so interupt thread to close
Thread.currentThread().interrupt();
//return;
//Thread.currentThread().stop(new InterruptedException("Attempting to close"));
}
goodData = input.read(readBuffer);
}
}
}
catch(Exception e)
{
System.out.println("closing "+Thread.currentThread().getName() +" because of an exception "+e.getClass());
return;
}
System.out.println("closing "+Thread.currentThread().getName());
}
}
我创建了一个虚拟的主类来演示这个问题
public class ExampleOfInterruptNotWorking
{
public static void main(String[] args)
{
byte[] bytesToWrite = new byte[]{0, 1, 2,3,4,5,6,65,23,65,21,54,13,54,1,76};
Consumer C;
Thread ConsumerThread;
PipedInputStream PIS = null;
PipedOutputStream POS = null;
try
{
PIS = new PipedInputStream();
POS = new PipedOutputStream(PIS);
C = new Consumer(PIS);
ConsumerThread = new Thread(C);
ConsumerThread.start();
POS.write(bytesToWrite);
POS.write(bytesToWrite);
bytesToWrite[1] = 27;
POS.write(bytesToWrite);
ConsumerThread.join();
}
catch(Exception e)
{
System.err.println("Unexpected exception in main");
e.printStackTrace(System.err);
}
finally
{
try
{
PIS.close();
POS.close();
}
catch(Exception ex)
{
//shouldn't happen in example
}
System.out.println("exiting main");
}
}
}
当您以编写的方式运行此代码时,使用者会检测到中断,但不会停止执行,直到管道为空(不是我想要的)。只是为了尝试,我改为Thread.stop()调用,它实现了我想要的功能,但我不想将其留在生产代码中。我意识到我可以使用一个简单的return语句,但这不是线程可以退出的唯一点,我希望有一些通用的退出代码来清理资源。所以,我的问题是,为什么消费者线程没有被中断?对于我来说,有没有一个好方法可以使用通用的退出代码
谢谢 您希望抛出哪个方法
InterruptedException
?不是扔它,也不是你的任何方法。那么,您认为这个已检查异常应该来自哪里呢
由于interrupt()
几乎没有在线程上设置interrupted
标志,因此代码无法工作。必须使用显式检查该标志<代码>InterruptedException仅在相关线程当时处于休眠或阻塞状态时才会抛出。因此,如果您中断不同的线程,并且该线程正在睡眠,sleep()
将抛出InterruptedException
现在来详细解决您的问题例外情况适用于例外情况。事实上,您的线程完成了处理并不是特例,这是您绝对期望的。出于同样的原因,读取超过结尾的文件不会引发异常-文件结尾是您应该明确期望的事情-所有文件都有结尾。此外,您不应该使用异常来控制程序流
在您的情况下,要么使用
return
语句(当run()
返回时,线程死亡),要么以其他方式中断循环。您发布的代码太多,无法分析。您希望抛出哪种方法InterruptedException
?不是扔它,也不是你的任何方法。那么,您认为这个已检查异常应该来自哪里呢
由于interrupt()
几乎没有在线程上设置interrupted
标志,因此代码无法工作。必须使用显式检查该标志<代码>InterruptedException仅在相关线程当时处于休眠或阻塞状态时才会抛出。因此,如果您中断不同的线程,并且该线程正在睡眠,sleep()
将抛出InterruptedException
现在来详细解决您的问题例外情况适用于例外情况。事实上,您的线程完成了处理并不是特例,这是您绝对期望的。出于同样的原因,读取超过结尾的文件不会引发异常-文件结尾是您应该明确期望的事情-所有文件都有结尾。此外,您不应该使用异常来控制程序流
在您的情况下,要么使用
return
语句(当run()
返回时,线程死亡),要么以其他方式中断循环。您发布的代码太多,无法分析。当线程处于睡眠状态、等待连接等(基本上是任何可中断的阻塞调用)时,会引发InterruptedException,并调用interrupt()
如果线程正在运行,那么将设置线程中断标志,但不会引发异常,您应该使用myThread.isInterrupted()
检查该标志
您可以在此处找到更多信息:
当线程正在睡眠、等待连接等(基本上是任何可中断的阻塞调用)时,会抛出InterruptedException,并调用interrupt() 如果线程正在运行,那么将设置线程中断标志,但不会引发异常,您应该使用
myThread.isInterrupted()
检查该标志
您可以在此处找到更多信息:
您可以简单地使用break来标记
OUTER:
while(input.available() > 0)
{
goodData = input.read(readBuffer);
while (goodData > 0 )
{
System.out.println(readBuffer[0]);
if ( readBuffer[0] == 27 )
{
System.out.println("Consumer: found closing byte and closing thread "+Thread.currentThread().getName());
//this is the last packet, so interupt thread to close
//Thread.currentThread().interrupt();
break OUTER;
//return;
//Thread.currentThread().stop(new InterruptedException("Attempting to close"));
}
goodData = input.read(readBuffer);
}
}
您可以简单地使用break来标记
OUTER:
while(input.available() > 0)
{
goodData = input.read(readBuffer);
while (goodData > 0 )
{
System.out.println(readBuffer[0]);
if ( readBuffer[0] == 27 )
{
System.out.println("Consumer: found closing byte and closing thread "+Thread.currentThread().getName());
//this is the last packet, so interupt thread to close
//Thread.currentThread().interrupt();
break OUTER;
//return;
//Thread.currentThread().stop(new InterruptedException("Attempting to close"));
}
goodData = input.read(readBuffer);
}
}
它没有被中断,因为它没有等待,您也没有向它发送消息。好方法是在完成编写后关闭流。返回语句看起来是您的最佳选择。你能试着演示一下你不能创建“一些清理资源的通用退出代码”的问题吗?通常,在finally block中执行此操作。@romac我真的不喜欢从正在读取流的东西下面关闭流。在这个特殊的例子中,我收到了一条关闭连接请求的返回消息。关于应用程序的设计,我不能保证关闭消息是最后发出的消息。正如在下面发布的“Exceptions for Exception cases”中所述,关闭流会导致IOException—而我早就知道流正在关闭。@JohnWatts我的印象是,在if块中添加一个return语句将退出该方法,绕过finally块。Nope。最后,除非VM进程(或正在执行的线程)本身死亡,否则如果您离开一个块,则总是会发生这种情况。但异常和返回并不能阻止它。它没有被中断,因为它没有等待,而且您没有向它发送消息。好方法是在完成编写后关闭流。返回语句看起来是您的最佳选择。你能试着演示一下你不能创建“一些清理资源的通用退出代码”的问题吗?通常,在finally block中执行此操作。@romac我真的不喜欢从正在读取流的东西下面关闭流。在这个特殊的例子中,我收到了一条关闭连接请求的返回消息。用多少钱