前言:最近在做一个关于数据同步的项目,其中需要使用到定时去执行一个同步的方法(每隔三分钟执行一次)。遇到了许多坑,所以在此总结一下。
一、开始没有使用定时器,而是使用了while(true) 去执行一个线程,在run方法中进行执行需要定时的方法。
public class SyncDBRunale implements Runnable{
@Override
public void run() {
while(true){
try {
System.out.println(" the synchronize start -------------------->>>>> ");
AllTableSyncService.doSync();
System.out.println(" the synchronize end -------------------->>>>> ");
} catch (Exception e) {
e.printStackTrace();
}finally{
System.out.println(" the synchronize finally -------------------->>>>> ");
}
System.out.println(" the synchronize end -------------------->>>>> ");
}
}
}
使用jetty或tomcat运行项目时候,执行情况是很好的定时执行。当打war包到部署打包环境运行时,项目中的同步方法并没有正常运行起来,Thread.sleep()线程睡了三分钟之后,线程睡过去了,并没有执行之后的代码。
原因:尚不明确,尚在学习中(欢迎各位大神指点)。
二、使用Timer做同步时,也出现了上述问题。
public class SyncDBRunale implements Runnable{
@Overridepublic void run() {
new Timer().schedule(new TimerTask() {
@Override
public void run() {
System.out.println(" the synchronize start -------------------->>>>> " + new Date(System.currentTimeMillis()));
AllTableSyncService.doSync(); //同步数据
System.out.println(" the synchronize end -------------------->>>>> " + new Date(System.currentTimeMillis()));
}
}, 0,180000);
}
}
同样的出现了上述的问题,不过是当执行的时间为5秒周期频率时,执行时间相对较长,当时过了几个小时,程序还是还莫名的终止运行,有时候只是执行几次了几次就挂了。
网上查了一个些原因,大致有以下几个
1)Timer是基于绝对时间的。容易受系统时钟的影响。
2) Timer只新建了一个线程来执行所有的TimeTask
3) Timer不会捕获TimerTask的异常,只是简单地停止,这样到会影响其他TimeTask的执行。
所以推测分析,在一个线程同启动多个定时任务,会发生异常,导致线程停止运行,而不会终止程序。若任务某次执行抛出未检测异常,线程挂了,后面的时间点就无法执行了,所以使用Timer定时去执行任务是不稳定的。
三、使用ScheduledThreadPoolExecutor
@Override
public void run() {
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2); //创建任务执行线程池
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(" the synchronize start -------------------->>>>> " + new Date(System.currentTimeMillis()));
AllTableSyncService.doSync();
System.out.println(" the synchronize end ----------------------->>>>> " + new Date(System.currentTimeMillis()));
}
}, 0, 3, TimeUnit.MINUTES);//0表示首次执行任务的延迟时间,3表示每次执行任务的间隔时间,TimeUnit.MINUTES执行的时间间隔数值单位
}
}
关于ScheduledThreadPoolExecutor的执行原理,我就不多述了。有兴趣的朋友可以参考一些大神们的讲解。
参考文章: