当一个线程被中断/杀死时,最终块可能无法执行吗?
在Java教程中,它说到try { ... } finally { ... }
:
注意:如果在执行try或catch代码时JVM退出,则finally块可能无法执行。 同样,如果执行try或catch代码的线程被中断或终止,则即使应用程序作为一个整体继续 ,finally块也可能不会执行。
是否可以中断或杀死一个线程( 我认为这是不可能的? ),以便在运行此线程的JVM 未退出/ finally
时不会执行finally
块? (我很困惑,因为上面引用的内容非常明确,误解的空间不大。)
编辑:将问题分解为其核心意图。
拉斐尔,我相信这是你追求的边缘案例之一。 如果线程在本机上被阻塞(例如从STDIN
或Socket
读取),并且JVM处于关闭状态,并且线程被中断,则finally
可能不会被调用。
以下示例在不调用弃用方法的情况下指示此情况:
-
Sleep
– 最后被调用。 -
SystemIn
– 最终未被调用。
这个例子非常人为,纯粹是出于演示目的:)
public class Interrupted { static final List 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(); } } } }
好吧,我的立场得到纠正。 可以使用弃用的方法:
@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
块。