为何future.isDone()必须在executorService.shutdown()之后调用?
嘿,我来帮你理清这个问题——其实你这里的核心误区不是future.isDone()必须在executorService.shutdown()之后调用,而是你的代码逻辑本身有问题,刚好shutdown()的加入让你巧合看到了输出而已。
咱们一步步拆解:
1. 无shutdown()时代码为啥没输出?
你写的循环是while (submit1.isDone()),这意思是只有当任务已经完成的时候,才会进入循环执行打印操作。但问题是,当你刚提交任务就立刻调用isDone(),此时任务大概率还在排队或者刚刚开始执行(线程池调度线程、任务启动都需要时间),所以isDone()会返回false,循环直接跳过,自然啥都打不出来。
2. 加了shutdown()后为啥能看到输出?
executorService.shutdown()的作用是告诉线程池:“别再接新任务了,但已经提交的任务要执行完”。它本身不会阻塞主线程,不过这里的关键是——调用shutdown()的这一小段时间里,你的Callable任务刚好执行完成了,所以后续isDone()返回true,循环才得以执行。这完全是 timing 问题,不是必然的:要是你把Callable任务改成耗时更长的(比如加个Thread.sleep(2000)),哪怕加了shutdown(),主线程调用isDone()的时候任务还没做完,你照样看不到输出。
3. 正确的写法应该是怎样的?
如果你想等待任务完成并获取结果,有两种更合理的方式:
- 直接用
submit1.get():这个方法是阻塞式的,会一直等到任务完成再返回结果,根本不需要循环判断isDone():Future<Integer> submit1 = executorService.submit(callable); // get()会阻塞到任务完成 System.out.println(submit1.get()); // 任务完成后再关闭线程池也完全没问题 executorService.shutdown(); - 非要用
isDone()的话,应该反过来判断(等待任务完成),最好加个短暂休眠避免CPU空转:Future<Integer> submit1 = executorService.submit(callable); // 等待任务完成,而不是任务完成才循环 while (!submit1.isDone()) { Thread.sleep(100); // 避免无意义的空转 } System.out.println(submit1.get()); executorService.shutdown();
4. 澄清两者的关系:
future.isDone()只是用来检查单个任务是否已经完成(不管是正常结束、抛异常还是被取消),它和线程池是否调用shutdown()没有任何强制绑定关系——你完全可以在线程池正常运行期间随时调用isDone()来监控任务状态。shutdown()只是用来管理线程池生命周期的方法,和单个任务的完成状态半毛钱关系都没有。
内容的提问来源于stack exchange,提问作者张卓鹏

