java - 中断方法不关闭 JVM

标签 java multithreading

我正在研究以下示例:

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

上面的 2 是可能的,因为主线程 hibernate 10 秒

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”会导致不同的行为(下面突出显示) - 有人可以解释一下这里到底发生了什么以及为什么吗?

Interrupts this thread.

Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.

If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

If this thread is blocked in an I/O operation upon an InterruptibleChannel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a java.nio.channels.ClosedByInterruptException.

If this thread is blocked in a java.nio.channels.Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked.

If none of the previous conditions hold then this thread's interrupt status will be set.

Interrupting a thread that is not alive need not have any effect.

最佳答案

这是因为中断标志对于线程的工作方式。

当你中断一个线程时,基本上只会发生一件事:中断标志被设置,这就是所有发生的事情。然后由该线程正在运行的代码决定其是否真正执行操作。

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

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

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

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

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

    Runnable task = () -> {
        while (!Thread.interrupted()) {
            System.out.println("Executing");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                return;
            }
        }
    };

无论中断何时发生,该方法都会退出。 99.99% 的情况下,它会在阻塞 sleep 时发生。那么该标志将为 false,并抛出异常。在不太可能的情况下,它在外部处理时发生,while 条件将拾取它。

请注意,如果您已引发中断标志并调用 Thread.sleep 之类的方法,则该方法将通过清除该标志并抛出 立即完成执行>中断异常。无论中断发生在哪里,上面的示例都会做同样的事情(静默退出 run 方法,并且中断标志将被清除)。

关于java - 中断方法不关闭 JVM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56799717/

相关文章:

java - 每 x 次调用函数而不阻塞 GUI Java

c++ - std::threads 是在用户空间还是内核空间中管理的?

c# - Vb.Net 的 with java 中的关键字?

c# - 如何检测主线程何时终止?

java - 仅用一个操作停止一个线程

java - 按下按钮后,它应该打开一个 JPanel

java - 控制ExecutorService每秒最多执行N个任务

java - 在mongodb子文档中查找

java - 如何处理Freemarker字符串模板?

java - 尝试在Java中的GUI中的表格下方添加文本字段