在the Java tutorial中,它说的是try { ... } finally { ... }
:
注意:如果在执行try或catch代码时JVM退出, 那么finally块可能不会执行。同样,如果线程 执行try或catch代码被中断或终止,最后 即使整个应用程序,块也可能无法执行 继续
线程可以 interrupted 或已杀死(I thought that was impossible?),以致finally
块不会在运行此线程的JVM 不退出/终止时执行? (我很困惑,因为上面引用的内容非常明确,误解的空间不大。)
编辑:将问题分解为核心意图。
答案 0 :(得分: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
块。
答案 1 :(得分:2)
拉斐尔,我相信这是你追求的边缘案例之一。如果线程在本机上被阻塞(例如从STDIN
或Socket
读取),并且JVM处于关闭状态,并且线程被中断,那么finally
可能不会被调用。
以下示例说明了这一点,但没有调用弃用的方法:
Sleep
- 最后被调用。SystemIn
- 最后未被调用。这个例子非常人为,纯粹是出于示范目的而提供的:)
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();
}
}
}
}