Timer定时器和ScheduledThreadPoolExecutor类执行任务时出现的问题

本文探讨了Java中实现定时任务的不同方式及其遇到的问题。从简单的while循环到使用Timer及ScheduledThreadPoolExecutor,对比了各自的优缺点与实际表现。指出ScheduledThreadPoolExecutor在稳定性与可靠性方面的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:最近在做一个关于数据同步的项目,其中需要使用到定时去执行一个同步的方法(每隔三分钟执行一次)。遇到了许多坑,所以在此总结一下。

一、开始没有使用定时器,而是使用了while(true) 去执行一个线程,在run方法中进行执行需要定时的方法。

public class SyncDBRunale implements Runnable{
@Override
public void run() {
 while(true){

try {

          System.out.println(" the synchronize start -------------------->>>>> ");

          AllTableSyncService.doSync(); 

         Thread.sleep(180000); //三分钟 同步数据一次  
 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{

@Override
public 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
public class SyncDBRunale implements Runnable{

@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的执行原理,我就不多述了。有兴趣的朋友可以参考一些大神们的讲解。


参考文章:

https://blog.youkuaiyun.com/zxh87/article/details/8588504(关于ScheduledThreadPoolExecutor类定时执行方法
https://www.jianshu.com/p/b47f2df9e917(Java中调度线程池ScheduledThreadPoolExecutor原理探究)





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值