本文目录导读:

- 使用 ScheduledExecutorService(原生方案)
- 使用 Spring @Scheduled 注解
- 使用 Quartz Scheduler
- 使用 TimerTask(不推荐)
- 使用线程控制的通用解决方案
- 选择建议
在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 |
功能足够、无需额外依赖 |
最佳实践建议:
- 避免使用
Timer,使用ScheduledExecutorService替代 - 使用
volatile或AtomicBoolean保证可见性 - 注意线程安全,使用适当的同步机制
- 考虑暂停时的资源释放和清理
- 添加适当的异常处理和日志记录