ScheduledExecutorService通过数据库控制启停

场景:项目启动时初始化循环定时,在一定的时间任务间隔内执行任务,如果用户在客户端更新了配置,那么循环定时需要重新执行。

分析:系统初始化给个方法运行起来,再写个controller通过页面调用后刷新定时即可。由于是固定的任务时间间隔,因此使用了scheduleAtFixedRate()实现效果,使用过ExecutorService的知道其中有以下几种方法:

void shutdown();
List<Runnable> shutdownNow();
boolean isShutdown();
boolean isTerminated();
boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException;
<T> Future<T> submit(Callable<T> task);
<T> Future<T> submit(Runnable task, T result);
......

其中比较关心的就是如果请求过来,查找数据库定时数据后,怎么刷新当前任务调度服务,很明显,shutdown();shutdownNow();isShutdown()不就是我们需要的吗?

 经过实验发现,调用shutdown()后,再次scheduleAtFixedRate(new Runable(), 0, timeBucket, TimeUnit.SECONDS)就会出问题,原因是shutdown()后,这个任务调度器就不再起作用了,就是说已经不存在了,源码中有说明:

if a security manager exists and shutting down this ExecutorService may manipulate threads that the caller is not permitted to modify because it does not hold.

这就出现了一个问题,如果我shutdown调度器后,我再创建一个周期操作将会不起作用,抛出异常,如下:

ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(task, 0, timeBucket, TimeUnit.SECONDS);
service.shutdown();
service.scheduleAtFixedRate(task, 0, timeBucket, TimeUnit.SECONDS);

第一次创建周期任务执行后,调用shutdown()方法,接着再创建一个周期任务, 这样将会抛出异常。

解决方法:

public class Task {

    private static ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();

    public void ApiSendJob(Integer flag) {
        //查询数据库,获取执行频次timeBucket
        String timeBucket= dataSource.getObject();
        //......
        long time = Long.parseLong(timeBucket.getConfigExtend());
        log.info("执行API接口定时任务,频次{}秒......", timeBucket);
        Runnable task = new Runnable() {
            @Override
            public void run() {
                try {
                    //TODO 查询定时,执行计划
                    log.info("API Task 正在执行......");
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };
        //此处传1,说明项目启动后会进入此分支创建周期任务
        if (flag == 1) {
            service.scheduleAtFixedRate(task, 0, time , TimeUnit.SECONDS);
        } else {
            //销毁之前创建的周期任务 
            service.shutdown();
            //重新创建ScheduledExecutorService 
            service = Executors.newSingleThreadScheduledExecutor();
            //创建新的周期任务
            service.scheduleAtFixedRate(task, 0, time , TimeUnit.SECONDS);
        }
    }
}

修改后测试:

初始化5秒/次

 修改后10秒/次

 关键点就是销毁后需要重新创建Executors.newSingleThreadScheduledExecutor()。当然,想要更严谨一些的业务逻辑,可以判断ScheduledFuture对象所有任务是否执行完毕,全部执行完毕后再shutdown(),如果业务是常态化的间隔执行,相对就没有那么高要求了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以在ScheduledExecutorService的定时任务中执行数据库操作,以下是一个示例代码: ```java import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class DatabaseTask { private ScheduledExecutorService scheduler; public DatabaseTask() { scheduler = Executors.newSingleThreadScheduledExecutor(); } public void startDatabaseTask() { // 每隔5秒执行一次任务 scheduler.scheduleAtFixedRate(new Runnable() { @Override public void run() { // 在这里执行数据库操作 updateDatabase(); } }, 0, 5, TimeUnit.SECONDS); } private void updateDatabase() { // 执行数据库操作的具体逻辑 // 这里只是一个示例,您需要替换为您自己的代码 System.out.println("执行数据库操作"); } public void stopDatabaseTask() { scheduler.shutdown(); } public static void main(String[] args) { DatabaseTask task = new DatabaseTask(); task.startDatabaseTask(); // 等待一段时间后停止任务 try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } task.stopDatabaseTask(); } } ``` 上述代码中,`startDatabaseTask()` 方法会创建一个ScheduledExecutorService,并使用`scheduleAtFixedRate()`方法设定定时任务的执行间隔。在任务的`run()`方法中,您可以执行需要进行的数据库操作。在这个示例中,只是简单地打印一条消息。 `stopDatabaseTask()` 方法用于停止定时任务。 您可以根据自己的需求,在`updateDatabase()`方法中编写相应的数据库操作逻辑。请确保在该方法中使用合适的方式连接和操作数据库,以免出现资源泄漏或性能问题。 请注意,这只是一个示例,您需要根据自己的实际情况进行修改和优化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值