当一个线程被中断/杀死时,最终块可能无法执行吗? [英] Might a finally block not get executed when a thread is interrupted/killed?

查看:207
本文介绍了当一个线程被中断/杀死时,最终块可能无法执行吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java教程中,它说的是 try {...} finally {...}


注意:如果是JVM在执行try或catch代码时退出,
然后finally块可能不会执行。同样,如果执行try或catch代码的线程
被中断或终止
,则最终
块可能无法执行,即使整个应用程序
继续

线程可以是 中断 被杀我认为这是不可能的?)这样,当运行此线程的JVM 退出时, finally 块将不会执行杀? (我很困惑,因为上面引用的内容非常明确,误解的空间不大。)

Is it true that a thread can be interrupted or killed (I thought that was impossible?) such that the finally block will not be executed while the JVM running this thread is not exited/killed? (I am puzzled because the quote above is pretty explicit about this, not much room for misunderstanding.)

编辑:将问题分解为其核心意图。

推荐答案

拉斐尔,我相信这是你所追求的优势之一。如果一个线程被本机阻塞(例如从 STDIN Socket 读取),并且JVM在关闭状态,并且线程被中断,然后 finally 可能不会被调用。

Rafael, I believe this is one of the edge cases you are after. If a thread is blocked on something native (eg reading from STDIN or a Socket), and the JVM is in a state of shutdown, and the thread is interrupted, then finally may not be invoked.

以下示例表明这一点不调用弃用方法:

The following example indicates this without invoking deprecated methods:


  1. 睡眠 - 最后 已调用。

  2. SystemIn - 最后未被调用。

  1. Sleep - finally is invoked.
  2. SystemIn - finally is not invoked.

这个例子非常人为,仅供说明之用:)

The example is very contrived, and is purely provided for demonstrative purposes :)

public class Interrupted {

  static final List<Thread> THREADS = Arrays.asList(
      new Thread(new Sleep()),
      new Thread(new SystemIn())
  );
  static final CountDownLatch LATCH = new CountDownLatch(THREADS.size());

  public static void main(String[] args) throws Exception {
    Runtime.getRuntime().addShutdownHook(new Thread(new ShutdownHook()));
    for (Thread thread : THREADS) {
      thread.start();
    }
    System.out.println("[main] Waiting for threads to start...");
    LATCH.await();
    System.out.println("[main] All started, time to exit");
    System.exit(0);
  }

  static abstract class BlockingTask implements Runnable {
    @Override
    public void run() {
      final String name = getClass().getSimpleName();
      try {
        LATCH.countDown();
        System.out.printf("[%s] is about to block...%n",name);
        blockingTask();
      } catch (Throwable e) {
        System.out.printf("[%s] ", name);
        e.printStackTrace(System.out);
      } finally {
        System.out.printf("[%s] finally%n", name);
      }
    }
    abstract void blockingTask() throws Throwable;
  }

  static class Sleep extends BlockingTask {
    @Override
    void blockingTask() throws Throwable {
      Thread.sleep(60 * 60 * 1000); // 1 hour
    }
  }

  static class SystemIn extends BlockingTask {
    @Override
    void blockingTask() throws Throwable {
      System.in.read();
    }
  }

  static class ShutdownHook implements Runnable {
    @Override
    public void run() {
      System.out.println("[shutdown-hook] About to interrupt blocking tasks...");
      for (Thread thread : THREADS) {
        thread.interrupt();
      }
      System.out.println("[shutdown-hook] Interrupted");
      try {
        for (int i=0; i<10; i++) {
          Thread.sleep(50L);
          System.out.println("[shutdown-hook] Still exiting...");
        }
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }

}

这篇关于当一个线程被中断/杀死时,最终块可能无法执行吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆