1. 使用 ScheduledExecutorService
实现定时任务
ScheduledExecutorService
是Java提供的一个定时任务调度器,可以用来定期执行任务。
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class OrderTimeoutTask {
private ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public void scheduleOrderTimeout(Order order, long timeout, TimeUnit unit) {
scheduler.schedule(() -> {
if (order.getStatus() == OrderStatus.PENDING) {
order.setStatus(OrderStatus.CLOSED);
System.out.println("Order " + order.getId() + " has been closed due to timeout.");
}
}, timeout, unit);
}
public void shutdown() {
scheduler.shutdown();
}
public static void main(String[] args) {
OrderTimeoutTask task = new OrderTimeoutTask();
Order order = new Order("123", OrderStatus.PENDING);
// 设置订单超时时间为30分钟
task.scheduleOrderTimeout(order, 30, TimeUnit.MINUTES);
// 模拟其他操作
try {
Thread.sleep(1000 * 60 * 5); // 等待5分钟
} catch (InterruptedException e) {
e.printStackTrace();
}
task.shutdown();
}
}
class Order {
private String id;
private OrderStatus status;
public Order(String id, OrderStatus status) {
this.id = id;
this.status = status;
}
public String getId() {
return id;
}
public OrderStatus getStatus() {
return status;
}
public void setStatus(OrderStatus status) {
this.status = status;
}
}
enum OrderStatus {
PENDING, CLOSED
}
2. 使用消息队列(如RabbitMQ、Kafka)实现延迟消息
消息队列可以处理延迟消息,适合分布式系统中的订单超时处理。
以RabbitMQ为例,可以使用延迟队列插件来实现订单超时关闭的功能。
2.1 RabbitMQ 延迟队列配置
首先,确保RabbitMQ安装了延迟队列插件。
2.2 发送延迟消息
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class OrderTimeoutProducer {
private final static String QUEUE_NAME = "order_timeout_queue";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection();
Channel channel = connection.createChannel()) {
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String orderId = "123";
String message = "Order " + orderId + " timeout";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");
}
}
}
2.3 消费延迟消息
import com.rabbitmq.client.*;
public class OrderTimeoutConsumer {
private final static String QUEUE_NAME = "order_timeout_queue";
public static void main(String[] argv) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.queueDeclare(QUEUE_NAME, false, false, false, null);
System.out.println(" [*] Waiting for messages. To exit press CTRL+C");
DeliverCallback deliverCallback = (consumerTag, delivery) -> {
String message = new String(delivery.getBody(), "UTF-8");
System.out.println(" [x] Received '" + message + "'");
// 处理订单超时逻辑
closeOrder(message);
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });
}
private static void closeOrder(String message) {
// 解析订单ID并关闭订单
System.out.println("Closing order: " + message);
}
}
3. 使用数据库定时任务
如果订单信息存储在数据库中,可以使用数据库的定时任务(如MySQL的事件调度器)来定期检查并关闭超时订单。
3.1 MySQL 事件调度器示例
CREATE EVENT order_timeout_event
ON SCHEDULE EVERY 1 MINUTE
DO
UPDATE orders SET status = 'CLOSED' WHERE status = 'PENDING' AND created_at < NOW() - INTERVAL 30 MINUTE;
-
ScheduledExecutorService
:适合单机应用,简单易用。 -
消息队列:适合分布式系统,能够处理高并发场景。
-
数据库定时任务:适合订单信息存储在数据库中的场景,依赖数据库的功能。