public JxMjkhTxController() { } public JxMjkhTxController(ScheduledExecutorService scheduledExecutorService, JxMjKhTxService jxMjKhTxService, ConstantProperties constantProperties) { this.scheduledExecutorService = scheduledExecutorService; this.jxMjKhTxService = jxMjKhTxService; this.constantProperties = constantProperties; } @PostConstruct public void init() { System.out.println("=====================================init-start========================"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())); scheduledExecutorService.scheduleAtFixedRate(() -> { try { new SaveResultTask(jxMjKhTxService, constantProperties).run(); } catch (Exception e) { e.printStackTrace(); log.error(e.getMessage()); } }, 0, 10, TimeUnit.MINUTES); } @GetMapping("/saveTxData") public List<Map<String, Object>> getResult() throws Exception { System.out.println("开始查询提醒接口数据"); return jxMjKhTxService.selectJxMjkhTxData(constantProperties.getJsbh()); }为什么我的定时任务定时跑的数据不对,但是我重启服务再跑数据就正确了,如何解决
时间: 2023-08-08 11:06:11 浏览: 73
几种定时任务(Timer、TimerTask、ScheduledFuture)的退出—结合真实案例【JAVA并发】.docx
根据你提供的代码,我猜测可能是定时任务与查询数据的接口之间存在竞争条件(race condition),导致数据不正确。具体来说,如果定时任务在查询数据接口执行期间启动,可能会导致查询的数据不正确。
为了解决这个问题,你可以将查询数据的接口与定时任务分离开来,让它们互不影响。具体的做法是,将查询数据的接口放到一个独立的控制器中,由客户端手动触发查询,而不是由定时任务自动触发。同时,你需要确保在查询数据时,定时任务没有在执行。你可以通过设置一个标志变量来实现这个功能,比如在定时任务启动时设置一个标志变量为 true,查询数据时判断这个标志变量是否为 true,如果是,则等待定时任务执行完毕再查询数据。
修改后的代码示例如下:
```
public class JxMjkhTxController {
private ScheduledExecutorService scheduledExecutorService;
private JxMjKhTxService jxMjKhTxService;
private ConstantProperties constantProperties;
private volatile boolean isRunning = false; // 标志变量
public JxMjkhTxController(ScheduledExecutorService scheduledExecutorService, JxMjKhTxService jxMjKhTxService, ConstantProperties constantProperties) {
this.scheduledExecutorService = scheduledExecutorService;
this.jxMjKhTxService = jxMjKhTxService;
this.constantProperties = constantProperties;
}
@PostConstruct
public void init() {
System.out.println("=====================================init-start========================"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
scheduledExecutorService.scheduleAtFixedRate(() -> {
try {
new SaveResultTask(jxMjKhTxService, constantProperties).run();
} catch (Exception e) {
e.printStackTrace();
log.error(e.getMessage());
}
}, 0, 10, TimeUnit.MINUTES);
}
@GetMapping("/saveTxData")
public List<Map<String, Object>> getResult() throws Exception {
if (isRunning) { // 如果定时任务正在执行,则等待
Thread.sleep(10000); // 等待 10 秒钟
}
System.out.println("开始查询提醒接口数据");
return jxMjKhTxService.selectJxMjkhTxData(constantProperties.getJsbh());
}
// 定时任务启动时设置标志变量为 true
class SaveResultTask implements Runnable {
private JxMjKhTxService jxMjKhTxService;
private ConstantProperties constantProperties;
public SaveResultTask(JxMjKhTxService jxMjKhTxService, ConstantProperties constantProperties) {
this.jxMjKhTxService = jxMjKhTxService;
this.constantProperties = constantProperties;
isRunning = true; // 设置标志变量为 true
}
@Override
public void run() {
try {
// 定时任务逻辑
} finally { // 定时任务执行完毕后,设置标志变量为 false
isRunning = false;
}
}
}
}
```
这样就可以避免竞争条件导致的数据不正确问题了。
阅读全文