本文目录导读:

- 使用 ScheduledExecutorService(推荐)
- 使用 Timer / TimerTask(简单场景)
- 使用 DelayQueue(任务调度)
- 复杂系统:使用 Redis 实现分布式延时任务
- 完整业务系统示例
- 使用建议
- 关键要点
我来详细介绍Java中实现延时任务的几种常见方式,并提供完整案例。
使用 ScheduledExecutorService(推荐)
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class ScheduledExecutorDemo {
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("HH:mm:ss");
private final ScheduledExecutorService scheduler;
private final AtomicInteger taskCounter = new AtomicInteger(0);
public ScheduledExecutorDemo(int poolSize) {
// 创建线程池
this.scheduler = Executors.newScheduledThreadPool(poolSize, runnable -> {
Thread thread = new Thread(runnable, "Scheduled-Task-Thread");
thread.setDaemon(true);
return thread;
});
}
// 单个延时任务
public void scheduleDelayedTask(Runnable task, long delay, TimeUnit unit) {
System.out.println("[" + now() + "] 任务已安排,将在 " + delay + " " + unit + " 后执行");
scheduler.schedule(() -> {
try {
System.out.println("[" + now() + "] 开始执行任务 #" +
taskCounter.incrementAndGet());
task.run();
} catch (Exception e) {
System.err.println("任务执行失败: " + e.getMessage());
}
}, delay, unit);
}
// 固定频率执行
public void scheduleAtFixedRate(Runnable task, long initialDelay,
long period, TimeUnit unit) {
scheduler.scheduleAtFixedRate(task, initialDelay, period, unit);
}
// 固定延迟执行(上次执行完后延迟)
public void scheduleWithFixedDelay(Runnable task, long initialDelay,
long delay, TimeUnit unit) {
scheduler.scheduleWithFixedDelay(task, initialDelay, delay, unit);
}
// 关闭任务
public void shutdown() {
scheduler.shutdown();
try {
if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
scheduler.shutdownNow();
}
} catch (InterruptedException e) {
scheduler.shutdownNow();
Thread.currentThread().interrupt();
}
}
private String now() {
return LocalDateTime.now().format(FORMATTER);
}
// 测试
public static void main(String[] args) throws InterruptedException {
ScheduledExecutorDemo demo = new ScheduledExecutorDemo(3);
// 单次延时任务
demo.scheduleDelayedTask(() ->
System.out.println("[" + demo.now() + "] 这是一次性延时任务"),
3, TimeUnit.SECONDS);
// 延迟2秒后,每5秒执行一次
demo.scheduleAtFixedRate(() ->
System.out.println("[" + demo.now() + "] 固定频率任务"),
2, 5, TimeUnit.SECONDS);
// 延迟1秒后,每次执行完延迟3秒
demo.scheduleWithFixedDelay(() -> {
System.out.println("[" + demo.now() + "] 固定延迟任务开始");
try {
Thread.sleep(1000); // 模拟任务执行时间
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}, 1, 3, TimeUnit.SECONDS);
Thread.sleep(20000);
demo.shutdown();
}
}
使用 Timer / TimerTask(简单场景)
import java.util.Timer;
import java.util.TimerTask;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class TimerDemo {
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("HH:mm:ss");
public static void main(String[] args) throws InterruptedException {
Timer timer = new Timer("Timer-Thread", true); // daemon线程
// 单次延时任务
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("[" + now() + "] 单次延时任务执行");
}
}, 3000); // 3秒后执行
// 固定延迟执行
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println("[" + now() + "] 定时任务执行");
}
}, 2000, 5000); // 2秒后开始,每5秒执行一次
Thread.sleep(15000);
timer.cancel();
}
private static String now() {
return LocalDateTime.now().format(FORMATTER);
}
}
使用 DelayQueue(任务调度)
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
// 延时任务类
class DelayedTask implements Delayed {
private final String taskName;
private final long executeTime; // 执行时间戳
private final Runnable task;
public DelayedTask(String taskName, Runnable task, long delay, TimeUnit unit) {
this.taskName = taskName;
this.task = task;
this.executeTime = System.currentTimeMillis() +
TimeUnit.MILLISECONDS.convert(delay, unit);
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(executeTime - System.currentTimeMillis(),
TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed other) {
return Long.compare(this.executeTime,
((DelayedTask) other).executeTime);
}
public void execute() {
task.run();
}
public String getTaskName() {
return taskName;
}
}
public class DelayQueueDemo {
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("HH:mm:ss");
private final DelayQueue<DelayedTask> taskQueue = new DelayQueue<>();
private static final AtomicInteger taskCounter = new AtomicInteger(0);
public void startWorker() {
Thread worker = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
DelayedTask task = taskQueue.take();
System.out.println("[" + now() + "] 执行任务: " +
task.getTaskName());
task.execute();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
}
}, "DelayQueue-Worker");
worker.setDaemon(true);
worker.start();
}
public void addTask(String name, Runnable task, long delay, TimeUnit unit) {
DelayedTask delayedTask = new DelayedTask(
name, task, delay, unit);
taskQueue.put(delayedTask);
System.out.println("[" + now() + "] 已添加任务: " + name +
", 延迟: " + delay + " " + unit);
}
private String now() {
return LocalDateTime.now().format(FORMATTER);
}
public static void main(String[] args) throws InterruptedException {
DelayQueueDemo demo = new DelayQueueDemo();
demo.startWorker();
// 添加不同延迟的任务
demo.addTask("任务A", () ->
System.out.println("[" + demo.now() + "] 任务A执行完成"),
3, TimeUnit.SECONDS);
demo.addTask("任务B", () ->
System.out.println("[" + demo.now() + "] 任务B执行完成"),
1, TimeUnit.SECONDS);
demo.addTask("任务C", () ->
System.out.println("[" + demo.now() + "] 任务C执行完成"),
5, TimeUnit.SECONDS);
Thread.sleep(8000);
}
}
复杂系统:使用 Redis 实现分布式延时任务
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Set;
import java.util.UUID;
public class RedisDelayedTask {
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("HH:mm:ss");
private final JedisPool jedisPool;
private final String taskQueueKey;
public RedisDelayedTask(String redisHost, int redisPort, String queueName) {
this.jedisPool = new JedisPool(redisHost, redisPort);
this.taskQueueKey = queueName;
}
// 添加延时任务
public void addDelayedTask(String taskId, int delaySeconds, String data) {
try (Jedis jedis = jedisPool.getResource()) {
long delayTimestamp = System.currentTimeMillis() / 1000 + delaySeconds;
jedis.zadd(taskQueueKey, delayTimestamp,
String.format("%s:%s", taskId, data));
System.out.println("[" + now() + "] 添加任务: " + taskId +
", 将在 " + delaySeconds + " 秒后执行");
}
}
// 获取到期任务
public Set<String> getDueTasks() {
try (Jedis jedis = jedisPool.getResource()) {
long currentTimestamp = System.currentTimeMillis() / 1000;
return jedis.zrangeByScore(taskQueueKey, 0, currentTimestamp);
}
}
// 清除已处理任务
public void removeTask(String task) {
try (Jedis jedis = jedisPool.getResource()) {
jedis.zrem(taskQueueKey, task);
}
}
// 启动扫描器
public void startScanner() {
Thread scanner = new Thread(() -> {
while (!Thread.currentThread().isInterrupted()) {
try {
Set<String> dueTasks = getDueTasks();
for (String task : dueTasks) {
processTask(task);
removeTask(task);
}
Thread.sleep(1000); // 每秒检查一次
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
} catch (Exception e) {
System.err.println("处理任务时出错: " + e.getMessage());
}
}
}, "Redis-Task-Scanner");
scanner.setDaemon(true);
scanner.start();
}
private void processTask(String task) {
System.out.println("[" + now() + "] 执行延时任务: " + task);
// 在这里执行实际的业务逻辑
}
private String now() {
return LocalDateTime.now().format(FORMATTER);
}
public static void main(String[] args) throws InterruptedException {
// 假设Redis在本地运行
RedisDelayedTask demo = new RedisDelayedTask("localhost", 6379, "delayed:tasks");
// 启动扫描器
demo.startScanner();
// 添加不同延迟的任务
for (int i = 1; i <= 5; i++) {
String taskId = UUID.randomUUID().toString().substring(0, 8);
demo.addDelayedTask(taskId, i * 2, "任务数据-" + i);
}
Thread.sleep(15000);
}
// 清理
public void shutdown() {
jedisPool.close();
}
}
完整业务系统示例
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicLong;
public class OrderCancelSystem {
private static final DateTimeFormatter FORMATTER =
DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private final ScheduledExecutorService scheduler;
private final ExecutorService taskExecutor;
private final ConcurrentMap<String, ScheduledFuture<?>> taskMap;
private final AtomicLong orderCounter;
public OrderCancelSystem() {
this.scheduler = Executors.newScheduledThreadPool(2);
this.taskExecutor = Executors.newFixedThreadPool(5);
this.taskMap = new ConcurrentHashMap<>();
this.orderCounter = new AtomicLong(0);
}
// 创建订单并设置超时自动取消
public String createOrder(String productId, int quantity,
long timeoutSeconds) {
String orderId = "ORDER" +
String.format("%06d", orderCounter.incrementAndGet());
System.out.println("[" + now() + "] 创建订单: " + orderId +
", 商品: " + productId + ", " +
timeoutSeconds + "秒后未支付将自动取消");
// 安排过期检测
OrderCancelTask cancelTask = new OrderCancelTask(orderId);
ScheduledFuture<?> future = scheduler.schedule(cancelTask,
timeoutSeconds, TimeUnit.SECONDS);
// 存储映射关系,以便后续可能的取消
taskMap.put(orderId, future);
return orderId;
}
// 取消定时任务(订单已支付)
public void cancelTask(String orderId) {
ScheduledFuture<?> future = taskMap.remove(orderId);
if (future != null) {
future.cancel(false);
System.out.println("[" + now() + "] 订单 " + orderId +
" 已支付,取消自动关闭");
}
}
// 关闭系统
public void shutdown() {
scheduler.shutdownNow();
taskExecutor.shutdownNow();
System.out.println("[" + now() + "] 系统已关闭");
}
private String now() {
return LocalDateTime.now().format(FORMATTER);
}
private class OrderCancelTask implements Runnable {
private final String orderId;
public OrderCancelTask(String orderId) {
this.orderId = orderId;
}
@Override
public void run() {
taskMap.remove(orderId); // 清理映射
// 使用线程池异步执行取消逻辑
taskExecutor.submit(() -> {
System.out.println("[" + now() + "] 订单 " + orderId +
" 超时未支付,已自动取消");
// 模拟取消操作
try {
Thread.sleep(500);
System.out.println("[" + now() + "] 订单 " + orderId +
" 取消操作完成,库存已恢复");
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
}
public static void main(String[] args) throws InterruptedException {
OrderCancelSystem system = new OrderCancelSystem();
// 创建订单,5秒后自动取消
String order1 = system.createOrder("商品A", 2, 5);
String order2 = system.createOrder("商品B", 1, 8);
Thread.sleep(3000);
// 用户支付了第一个订单
System.out.println("[" + system.now() + "] 用户支付订单 " + order1);
system.cancelTask(order1);
Thread.sleep(10000);
// 创建更多订单测试
String order3 = system.createOrder("商品C", 3, 2);
Thread.sleep(5000);
system.shutdown();
}
}
使用建议
| 场景 | 推荐方案 | 优势 |
|---|---|---|
| 单机应用 | ScheduledExecutorService | 灵活、高效、线程池管理 |
| 简单任务调度 | Timer/TimerTask | 简单易用 |
| 内存级延迟队列 | DelayQueue | 支持复杂排序 |
| 分布式系统 | Redis ZSet | 支持集群、持久化 |
| 企业级调度 | Quartz | 功能强大、支持CRON表达式 |
关键要点
- 线程安全性:确保任务线程安全
- 异常处理:捕获并处理任务异常
- 资源管理:及时关闭线程池
- 优雅关闭:使用shutdown/shutdownNow方法
- 监控告警:添加日志和监控机制
根据实际需求选择合适的方案,注意考虑性能和并发需求。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播