Java案例如何暂停定时任务?

wen java案例 12

本文目录导读:

Java案例如何暂停定时任务?

  1. 使用 ScheduledExecutorService(原生方案)
  2. 使用 Spring @Scheduled 注解
  3. 使用 Quartz Scheduler
  4. 使用 TimerTask(不推荐)
  5. 使用线程控制的通用解决方案
  6. 选择建议

在Java中暂停定时任务有多种方式,具体取决于你使用的定时任务框架,以下是几种常见方案:

使用 ScheduledExecutorService(原生方案)

基础实现

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
public class PausableScheduler {
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private ScheduledFuture<?> scheduledFuture;
    private final AtomicBoolean paused = new AtomicBoolean(false);
    private final Object lock = new Object();
    public void start() {
        scheduledFuture = scheduler.scheduleAtFixedRate(() -> {
            synchronized (lock) {
                while (paused.get()) {
                    try {
                        lock.wait(); // 暂停时等待
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        return;
                    }
                }
            }
            // 执行任务逻辑
            System.out.println("Task executed at: " + System.currentTimeMillis());
        }, 0, 1, TimeUnit.SECONDS);
    }
    public void pause() {
        paused.set(true);
        System.out.println("Task paused");
    }
    public void resume() {
        synchronized (lock) {
            paused.set(false);
            lock.notifyAll(); // 唤醒所有等待线程
            System.out.println("Task resumed");
        }
    }
    public void stop() {
        if (scheduledFuture != null) {
            scheduledFuture.cancel(false);
        }
        scheduler.shutdown();
    }
}
// 使用示例
public class Demo {
    public static void main(String[] args) throws InterruptedException {
        PausableScheduler scheduler = new PausableScheduler();
        scheduler.start();
        Thread.sleep(3000);
        scheduler.pause(); // 暂停
        Thread.sleep(3000);
        scheduler.resume(); // 恢复
        Thread.sleep(3000);
        scheduler.stop(); // 停止
    }
}

更优雅的实现(使用 CountDownLatch)

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
public class GracefulPausableScheduler {
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private final AtomicBoolean running = new AtomicBoolean(true);
    private volatile CountDownLatch pauseLatch;
    public void start() {
        scheduler.scheduleAtFixedRate(() -> {
            if (!running.get()) return;
            // 检查是否暂停
            if (pauseLatch != null) {
                try {
                    pauseLatch.await();
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    return;
                }
            }
            // 执行任务
            try {
                System.out.println("Task running at: " + System.currentTimeMillis());
                // 模拟任务执行
                Thread.sleep(500);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        }, 0, 1, TimeUnit.SECONDS);
    }
    public void pause() {
        pauseLatch = new CountDownLatch(1);
        System.out.println("Task paused");
    }
    public void resume() {
        if (pauseLatch != null) {
            pauseLatch.countDown();
            pauseLatch = null;
            System.out.println("Task resumed");
        }
    }
    public void stop() {
        running.set(false);
        scheduler.shutdown();
        // 确保恢复所有暂停的任务
        if (pauseLatch != null) {
            pauseLatch.countDown();
        }
    }
}

使用 Spring @Scheduled 注解

import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.AtomicBoolean;
@Component
@EnableScheduling
public class PausableTask {
    private final AtomicBoolean paused = new AtomicBoolean(false);
    private final Object lock = new Object();
    @Scheduled(fixedRate = 1000)
    public void executeTask() {
        if (paused.get()) {
            synchronized (lock) {
                while (paused.get()) {
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        return;
                    }
                }
            }
        }
        System.out.println("Task running at: " + System.currentTimeMillis());
    }
    public void pause() {
        paused.set(true);
    }
    public void resume() {
        synchronized (lock) {
            paused.set(false);
            lock.notifyAll();
        }
    }
}

更优雅的 Spring 实现(使用 Conditional)

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.AtomicBoolean;
@Component
public class ConditionalTask {
    private final AtomicBoolean enabled = new AtomicBoolean(true);
    @Scheduled(fixedRate = 1000)
    public void executeTask() {
        if (!enabled.get()) {
            System.out.println("Task is disabled, skipping execution");
            return;
        }
        System.out.println("Task running at: " + System.currentTimeMillis());
    }
    public void pause() {
        enabled.set(false);
    }
    public void resume() {
        enabled.set(true);
    }
}

使用 Quartz Scheduler

import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
public class QuartzPausableScheduler {
    private Scheduler scheduler;
    public void start() throws SchedulerException {
        scheduler = StdSchedulerFactory.getDefaultScheduler();
        JobDetail job = JobBuilder.newJob(MyJob.class)
            .withIdentity("myJob", "group1")
            .build();
        Trigger trigger = TriggerBuilder.newTrigger()
            .withIdentity("myTrigger", "group1")
            .startNow()
            .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                .withIntervalInSeconds(1)
                .repeatForever())
            .build();
        scheduler.scheduleJob(job, trigger);
        scheduler.start();
    }
    public void pause() throws SchedulerException {
        scheduler.pauseJob(JobKey.jobKey("myJob", "group1"));
        // 或者暂停触发器
        // scheduler.pauseTrigger(TriggerKey.triggerKey("myTrigger", "group1"));
        System.out.println("Task paused");
    }
    public void resume() throws SchedulerException {
        scheduler.resumeJob(JobKey.jobKey("myJob", "group1"));
        System.out.println("Task resumed");
    }
    public void stop() throws SchedulerException {
        scheduler.shutdown();
    }
    public static class MyJob implements Job {
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            System.out.println("Quartz task running at: " + System.currentTimeMillis());
        }
    }
}

使用 TimerTask(不推荐)

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.atomic.AtomicBoolean;
public class TimerPausableTask {
    private Timer timer;
    private volatile TimerTask timerTask;
    private final AtomicBoolean paused = new AtomicBoolean(false);
    public void start() {
        timer = new Timer();
        timerTask = new TimerTask() {
            @Override
            public void run() {
                if (!paused.get()) {
                    System.out.println("Timer task running at: " + System.currentTimeMillis());
                }
            }
        };
        timer.scheduleAtFixedRate(timerTask, 0, 1000);
    }
    public void pause() {
        paused.set(true);
        if (timerTask != null) {
            timerTask.cancel();
        }
    }
    public void resume() {
        paused.set(false);
        if (timer != null) {
            timerTask = new TimerTask() {
                @Override
                public void run() {
                    if (!paused.get()) {
                        System.out.println("Timer task running at: " + System.currentTimeMillis());
                    }
                }
            };
            timer.scheduleAtFixedRate(timerTask, 0, 1000);
        }
    }
    public void stop() {
        if (timer != null) {
            timer.cancel();
            timer.purge();
        }
    }
}

使用线程控制的通用解决方案

import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
public class GenericPausableTask {
    private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
    private ScheduledFuture<?> future;
    private final AtomicBoolean isPaused = new AtomicBoolean(false);
    private final ReentrantLock lock = new ReentrantLock();
    private final Condition pauseCondition = lock.newCondition();
    public void start() {
        future = executor.scheduleWithFixedDelay(() -> {
            lock.lock();
            try {
                while (isPaused.get()) {
                    pauseCondition.await();
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                return;
            } finally {
                lock.unlock();
            }
            // 执行实际任务
            executeJob();
        }, 0, 1, TimeUnit.SECONDS);
    }
    private void executeJob() {
        System.out.println("Task executed at: " + System.currentTimeMillis());
    }
    public void pause() {
        lock.lock();
        try {
            isPaused.set(true);
        } finally {
            lock.unlock();
        }
    }
    public void resume() {
        lock.lock();
        try {
            isPaused.set(false);
            pauseCondition.signalAll();
        } finally {
            lock.unlock();
        }
    }
    public void stop() {
        if (future != null) {
            future.cancel(false);
        }
        executor.shutdown();
        // 唤醒所有等待线程
        lock.lock();
        try {
            pauseCondition.signalAll();
        } finally {
            lock.unlock();
        }
    }
}

选择建议

场景 推荐方案 理由
简单并发控制 ScheduledExecutorService 轻量、内置、易于控制
Spring Boot 应用 @Scheduled + 条件控制 集成简单、声明式编程
复杂调度需求 Quartz Scheduler 支持CRON、集群、持久化
简单定时任务 ScheduledExecutorService 功能足够、无需额外依赖

最佳实践建议

  1. 避免使用 Timer,使用 ScheduledExecutorService 替代
  2. 使用 volatileAtomicBoolean 保证可见性
  3. 注意线程安全,使用适当的同步机制
  4. 考虑暂停时的资源释放和清理
  5. 添加适当的异常处理和日志记录

抱歉,评论功能暂时关闭!