Dropwizard使用dropwizard-sundial实现定时任务单独线程运行报错问题
问题原因与解决方案
实例化报错根因
Sundial底层基于Quartz实现,SimpleJobFactory会通过反射调用Job类的public无参构造方法创建实例,你的操作触发了以下问题:
- 给
CronJob添加自定义构造函数后,Java会自动移除默认的无参构造方法,导致反射找不到对应构造方法,触发NoSuchMethodException报错 - 实现
Runnable接口本身不会直接导致报错,但如果实现过程中修改了类结构导致无参构造丢失,也会触发该错误,且该操作本身属于多余操作
解决实例化报错
如果必须保留自定义构造函数,只需显式声明public无参构造即可,示例代码如下:
import org.knowm.sundial.Job; import org.knowm.sundial.annotations.CronTrigger; import org.knowm.sundial.exceptions.JobInterruptException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @CronTrigger(cron = "* * * * * ? *") public class CronJob extends Job { private static final Logger logger = LoggerFactory.getLogger(CronJob.class); // 显式声明无参构造 public CronJob() {} // 你的自定义构造函数 public CronJob(String customParam) { // 自定义初始化逻辑 } @Override public void doRun() throws JobInterruptException { logger.info("Hello from Cron Job"); } }
不需要额外实现Runnable接口,无意义还容易引入额外问题。
实现定时任务独立线程运行
Sundial默认已经实现了Job的独立线程运行:调度线程池和Dropwizard的Jetty请求线程、主业务线程完全隔离,每个Job的执行都会分配独立线程,默认线程池大小为10。
如果需要自定义调度线程池配置,直接在Dropwizard的配置文件中修改Sundial参数即可:
sundial: threadPoolSize: 20 # 按需调整线程池大小,适配同时运行的任务数量 startDelay: 0 runOnStart: false
如果需要Job内部的业务逻辑再拆分多线程异步执行,直接在doRun方法中将任务提交到你自定义的全局业务线程池即可:
@Override public void doRun() throws JobInterruptException { // 全局共用的业务线程池,不要每次执行Job都新建线程池 customBusinessThreadPool.execute(() -> { // 你的异步业务逻辑 logger.info("异步执行任务,当前线程:{}", Thread.currentThread().getName()); }); }
内容的提问来源于stack exchange,提问作者harry123
相关产品推荐
相关产品推荐

