为何Executor线程在主类结束后持续运行,而普通线程不会?
为什么两段代码的程序终止行为不同?
这个问题的核心在于线程是否被实际启动,以及线程池工作线程的存活特性,咱们一步步拆解清楚:
第一段代码:线程池的用户线程阻止JVM退出
先看你的第一段代码:
Executor executor = Executors.newFixedThreadPool(1); executor.execute(new Runnable() { public void run() { try { System.out.println("sleep"); Thread.sleep(5000); } catch (InterruptedException e) { System.out.println("Interrupted, so exiting."); } } });
这里你做了两个关键操作:
- 通过
Executors.newFixedThreadPool(1)创建的固定大小线程池,它的核心线程默认不会自动销毁——即使任务执行完毕,工作线程也会留在池中等待新任务,不会自行结束。 - 调用
execute()提交任务后,线程池会启动一个用户线程来执行你的Runnable逻辑。
JVM的终止规则是:只有当所有用户线程都执行完毕后,JVM才会退出。而线程池的这个工作线程在睡5秒完成任务后,依然处于活跃等待状态,属于未结束的用户线程,所以JVM会一直等待,程序自然无法终止。
如果想让这段代码的程序正常终止,你需要手动关闭线程池,比如在execute()之后添加((ExecutorService)executor).shutdown(),这样线程池会在任务执行完毕后销毁工作线程,JVM就能正常退出了。
第二段代码:线程根本没被启动
再看你的第二段代码:
Thread t = new Thread(new Runnable() { public void run() { try { Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } } });
这里你只是创建了一个Thread对象,但从来没有调用t.start()方法启动这个线程!也就是说,Runnable里的休眠逻辑根本没有被执行,程序中只有主线程在运行。当主线程执行完这段代码后,没有其他活跃的用户线程,JVM直接终止,所以程序看起来正常结束了。
如果你给这段代码加上t.start(),会发现程序也不会终止——因为启动后的Thread默认是用户线程,它会执行5秒休眠,期间JVM会等待它执行完毕才会退出。
内容的提问来源于stack exchange,提问作者Nick
相关产品推荐
相关产品推荐

