Java任务无执行且程序无限运行问题求助
排查自定义任务未执行且程序无限运行的建议
咱们来梳理下针对这个问题的关键排查方向——这类问题基本都和自定义任务的实现细节,或者ExecutorService的生命周期管理有关:
检查自定义任务的接口实现是否正确
如果你是从Runnable改过来的,要确认自定义任务类是否正确实现了Runnable或Callable接口,并且重写了对应的方法:- 若是实现
Runnable,必须重写public void run()方法,注意方法名、返回值、权限修饰符都不能错; - 若是实现
Callable,要重写public V call()方法(V是你指定的返回类型)。
如果没正确重写这些方法,ExecutorService根本找不到要执行的逻辑,自然不会跑你的业务代码。
- 若是实现
确认任务是否被正确提交到ExecutorService
你有没有调用execute()(针对Runnable)或者submit()(支持Runnable/Callable)方法把任务提交给线程池?如果只是创建了任务对象但没提交,那任务肯定不会被执行。另外要检查提交的是不是你的自定义任务实例,别不小心提交了空对象或者其他无关对象。排查ExecutorService的生命周期配置
程序无限运行的问题大概率是线程池没被正确关闭:- 像
FixedThreadPool这类核心线程数不为0的线程池,核心线程会一直存活等待新任务,导致程序无法自动退出。你需要在所有任务提交完成后,调用shutdown()来触发线程池的终止流程,还可以配合awaitTermination()等待任务全部完成:executorService.shutdown(); try { // 等待60秒让所有任务完成 if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) { // 超时后强制关闭 executorService.shutdownNow(); } } catch (InterruptedException e) { // 被中断时强制关闭 executorService.shutdownNow(); } - 另外如果用了无界任务队列,且任务一直没处理完,也可能导致程序挂起,但结合你说的任务逻辑没执行,这个可能性相对低一些,不过也可以检查下队列的配置。
- 像
检查任务内部的异常处理
ExecutorService会默默地吃掉任务执行时的未捕获异常(尤其是Runnable任务的情况),导致你看起来逻辑没执行,但其实是执行到一半抛出异常终止了:- 建议在任务的
run()或call()方法里加上全局try-catch,打印异常信息:@Override public void run() { try { // 你的业务逻辑代码 } catch (Exception e) { e.printStackTrace(); // 或者用日志框架记录异常 } } - 如果是Callable任务,提交后返回的
Future对象一定要调用get()方法,这个方法会抛出任务执行时的异常,能帮你快速定位问题。
- 建议在任务的
用调试和日志定位问题
- 在NetBeans里给自定义任务的
run()/call()方法设置断点,看看断点有没有被触发:如果没触发,说明任务根本没被执行;如果触发了,就一步步调试看哪一步出了问题。 - 在任务的关键节点添加日志(比如
System.out.println()或者日志框架),确认任务是否进入了执行方法,以及执行到哪一步停止了。
- 在NetBeans里给自定义任务的
检查自定义任务的初始化逻辑
看看自定义任务的构造函数有没有问题,是不是某些依赖对象为null,或者必要的参数没正确传入,导致执行逻辑时抛出异常但没被捕获?可以在构造函数里加日志或者断点,确认任务实例的状态是否正确。
内容的提问来源于stack exchange,提问作者Azog the Debugger
相关产品推荐
相关产品推荐

