3

Java教程中它说try { ... } finally { ... }

注意:如果在执行 try 或 catch 代码时 JVM 退出,则 finally 块可能不会执行。同样,如果执行 try 或 catch 代码的线程被中断或杀死,即使应用程序作为一个整体继续运行,finally 块也可能不会执行。

一个线程是否可以被中断杀死我认为这是不可能的?)这样在运行该线程的 JVM没有退出/杀死finally时该块不会被执行?(我很困惑,因为上面的引用对此非常明确,没有太大的误解空间。)

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

4

2 回答 2

3

好吧,我的立场是正确的。可以通过使用不推荐使用的方法:

@Test
public void testThread() throws Exception {
    Thread thread = new Thread(new MyRunnable());
    thread.start();
    Thread.sleep(100);
    thread.suspend();
    Thread.sleep(2000);
}

class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("Start");
        try {
            Thread.sleep(1500);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            System.out.println("Done");
        }
    }
}

由于在线程休眠时(很可能)会发生暂停,因此该finally块将永远不会被执行。

于 2013-10-23T12:18:11.993 回答
2

拉斐尔,我相信这是你所追求的边缘案例之一。如果线程在本机(例如读取STDIN或读取Socket)上被阻塞,并且 JVM 处于关闭状态,并且线程被中断,则finally可能不会被调用。

以下示例在不调用已弃用方法的情况下表明了这一点:

  1. Sleep- finally调用。
  2. SystemIn- finally没有被调用。

这个例子非常做作,纯粹是为了演示目的:)

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();
      }
    }
  }

}
于 2015-04-28T15:20:08.237 回答