Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 中断方法不关闭JVM_Java_Multithreading - Fatal编程技术网

Java 中断方法不关闭JVM

Java 中断方法不关闭JVM,java,multithreading,Java,Multithreading,我在玩下面的例子: public static void interrupted() throws InterruptedException { Runnable task = () -> { while(true && !Thread.currentThread().isInterrupted()) { System.out.println("task executing"); t

我在玩下面的例子:

public static void interrupted() throws InterruptedException {
    Runnable task = () -> {
        while(true && !Thread.currentThread().isInterrupted()) {
            System.out.println("task executing");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    
    Thread thread = new Thread(task);
    
    thread.start();
    //lets allow spawned thread to run by sleeping main thread for 10 seconds 
    Thread.currentThread().sleep(10000);
    thread.interrupt();
}
当我运行此方法时,我期望:

1通过Runnable启动的任务将运行几次并打印SOP

由于主线程休眠10秒,因此可以使用上面的2

3一旦主线程唤醒,它将调用生成的线程上的中断

4在Runnable任务中,我们正在检查isInterrupted,因此应该触发它,并且生成的线程应该退出,从而允许JVM退出

但是,这并没有发生,eclipse/jvm显示生成的线程仍在运行while循环

这是控制台:

task executing
task executing
java.lang.InterruptedException: sleep interrupted
at java.lang.Thread.sleep(Native Method)
at basics.StopEx.lambda$1(StopEx.java:39)
at java.lang.Thread.run(Thread.java:748)
task executing
task executing
task executing
task executing
........
关于中断的java文档似乎表明调用“sleep”会导致不同的行为(下面突出显示)——有人能解释一下这里到底发生了什么以及为什么吗

中断此线程

除非当前线程中断自身(这是始终允许的),否则将调用此线程的checkAccess方法,这可能会导致抛出SecurityException

如果此线程在调用对象类的wait()、wait(long)或wait(long,int)方法时被阻塞,或者在调用此类的join()、join(long)、join(long,int)、sleep(long)或sleep(long,int)方法时被阻塞,则其中断状态将被清除,并将接收到中断异常。

如果该线程在中断通道上的I/O操作中被阻塞,那么该通道将被关闭,线程的中断状态将被设置,线程将收到java.nio.channels.ClosedByInterruptException

如果该线程在java.nio.channels.Selector中被阻塞,那么该线程的中断状态将被设置,并且它将立即从选择操作返回,可能带有非零值,就像调用了选择器的唤醒方法一样

如果前面的条件都不成立,那么将设置该线程的中断状态

中断一个非活动线程不需要有任何效果


这是带有打印语句的代码

publicstaticvoidinterrupted()抛出InterruptedException{
可运行任务=()->
{
while(true&!Thread.currentThread().isInterrupted()){
System.out.println(“任务执行”);
试一试{
睡眠(5000);
}
捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
//这是假的。
System.out.println(Thread.currentThread().isInterrupted());
}
}
};

一旦中断状态被处理,线程将不再被视为处于中断状态,因此循环将继续。

这是因为中断标志如何对线程起作用

当你中断一个线程时,基本上只会发生一件事:设置中断标志,这就是所有发生的事情。然后这个线程运行的代码决定它是否真的做了一些事情

一般的想法是,如果可以的话,可以中止正在做的事情,并抛出一些合理的异常

java中内置的一些方法保证了这正是它们的工作方式。您可以很容易地识别它们:它们都声明为抛出
InterruptedException
。有许多方法故意不定义中断时的行为(这取决于操作系统):所有阻塞I/O方法的行为都是这样的。如果您处于阻塞网络读取中,并且中断了在读取中被阻塞的线程,则可能导致读取调用出现IOException,或者..不是

更重要的是,当“处理”中断时(中止+抛出异常就是处理它!),该标志被清除

请注意,如果您使用标准的检查方法,即
Thread.interrupted()
,则检查该标志已将其清除。此方法检查您自己线程的中断标志并将其清除。使用此方法:您编写了
if
语句或诸如此类的语句来处理中断,这意味着您已处理了该中断

因此,如果您只想返回以响应被中断,正确的代码是:

Runnable任务=()->{
而(!Thread.interrupted()){
系统输出打印项次(“执行”);
试一试{
睡眠(5000);
}捕捉(中断异常e){
返回;
}
}
};
无论中断何时发生,此方法都将退出。在99.99%的情况下,它会在阻塞睡眠时发生。然后标志将为false,并引发异常。在不太可能的情况下,它会在外部处理时发生,while条件会拾取它


请注意,如果您触发了中断标志,并调用了类似于
Thread.sleep
的方法,则该方法将通过清除标志并抛出
InterruptedException
立即完成执行。中断发生在何处并不重要,上面的示例将执行相同的操作(以静默方式退出运行方法,中断标志将被清除)。

InterruptedException
Thread.isInterrupted()
实际上是非常独立的。在长时间运行的循环中使用
sleep()
时引入了复杂性。您的
睡眠(5000)
实际上是清除
isInterrupted
标志并抛出
InterruptedException

如果您尝试以下操作,您将看到在
interrupt()
线程时实际上没有引发
InterruptException

    @Override public void run() {
        int b = 0;
        while (true) {
            if (b++ == 0) System.out.println("running...");
        }
    }
教训是,您确实需要检查异常和标志,但它们不应相互依赖。例如,您的示例捕获异常,但依赖标志来执行
    while (!Thread.currentThread().isInterrupted()) { // out of the loop when flag is raised 
        try {   
            //......
        } 
        catch (InterruptedException e) { 
            break;//exit loop when exception thrown
        }
    }

    // Or:
    try {   
        while (!Thread.currentThread().isInterrupted()) { // exit loop when flag is raised
            //.....
        }
    } 
    catch (InterruptedException e) { 
        // no need to break, as we're already outside
    }