Để xử lý tác vụ trì hoãn, các giải pháp phổ biến bao gồm hàng đợi tin nhắn hoặc Redis zset. Tuy nhiên với dự án nhỏ, JDK cung cấp DelayQueue - giải pháp nhẹ không yêu cầu cài đặt thêm thành phần ngoài.
Đầu tiên, định nghĩa lớp thực thể triển khai interface Delayed:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.Delayed;
public class DeferredTask implements Delayed {
private final long executionTime;
private final String payload;
public DeferredTask(String payload, long triggerAt) {
this.payload = payload;
this.executionTime = triggerAt;
}
public DeferredTask(String payload, int delay, TimeUnit unit) {
this.payload = payload;
this.executionTime = System.currentTimeMillis() + unit.toMillis(delay);
}
@Override
public long getDelay(TimeUnit unit) {
long remaining = executionTime - System.currentTimeMillis();
return unit.convert(remaining, TimeUnit.MILLISECONDS);
}
@Override
public int compareTo(Delayed other) {
DeferredTask task = (DeferredTask) other;
return Long.compare(this.executionTime, task.executionTime);
}
// Getter methods
}
Tiếp theo, tạo bộ quản lý hàng đợi với luồng xử lý bất đồng bộ:
import java.util.concurrent.DelayQueue;
public class TaskScheduler {
private final DelayQueue<DeferredTask> queue = new DelayQueue<>();
public void schedule(DeferredTask task) {
queue.put(task);
System.out.println("Đã lên lịch: " + task.getPayload());
}
public void startProcessing() {
new Thread(() -> {
while (true) {
try {
DeferredTask task = queue.take();
System.out.println("Xử lý: " + task.getPayload()
+ " | Thời điểm: " + task.getExecutionTime());
// Thêm logic xử lý tại đây
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}, "task-processor").start();
}
}
Kiểm thử chức năng:
public class SchedulerDemo {
public static void main(String[] args) {
TaskScheduler scheduler = new TaskScheduler();
scheduler.startProcessing();
scheduler.schedule(new DeferredTask("Tác vụ 1", 5, TimeUnit.SECONDS));
scheduler.schedule(new DeferredTask("Tác vụ 2", 2, TimeUnit.SECONDS));
}
}
Kết quả mẫu:
Đã lên lịch: Tác vụ 1
Đã lên lịch: Tác vụ 2
Xử lý: Tác vụ 2 | Thời điểm: 1678888888888
Xử lý: Tác vụ 1 | Thời điểm: 1678888891888
Giải pháp này phù hợp cho hệ thống đơn giản, kết hợp DelayQueue với scheduled tasks để giảm tải bộ nhớ. Với hệ thống phân tán, nên dùng giải pháp hàng đợi bên thứ ba để dễ mở rộng.