Java中的延时队列是一种特殊的数据结构,它允许我们在指定的时间后才处理队列中的元素。常见的场景包括任务调度、定时消息发送、限流等。下面将总结几种常见的延时队列实现方案,并提供代码示例。

1. 基于java.util.concurrent.PriorityBlockingQueue的实现

PriorityBlockingQueue是Java提供的一个线程安全的优先级队列。在实现延时队列时,我们可以将任务的执行时间作为优先级进行管理。

import java.util.concurrent.*;
import java.util.Date;

class DelayedTask implements Delayed {
    private final long delay;
    private final long trigger;
    private final String name;

    public DelayedTask(long delay, String name) {
        this.delay = delay;
        this.trigger = System.currentTimeMillis() + delay;
        this.name = name;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long diff = trigger - System.currentTimeMillis();
        return unit.convert(diff, TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        if (this.trigger < ((DelayedTask) o).trigger) {
            return -1;
        }
        if (this.trigger > ((DelayedTask) o).trigger) {
            return 1;
        }
        return 0;
    }

    public void run() {
        System.out.println("Executing task: " + name + " at " + new Date());
    }
}

public class DelayQueueExample {
    public static void main(String[] args) throws InterruptedException {
        DelayQueue<DelayedTask> queue = new DelayQueue<>();

        queue.put(new DelayedTask(3000, "Task 1"));
        queue.put(new DelayedTask(1000, "Task 2"));
        queue.put(new DelayedTask(2000, "Task 3"));

        while (!queue.isEmpty()) {
            DelayedTask task = queue.take();
            task.run();
        }
    }
}

在这个示例中,我们定义了一个 DelayedTask 类,它实现了 Delayed 接口,并重写了 getDelaycompareTo 方法。在 main 方法中,我们创建了一个 DelayQueue,将不同延迟的任务放入队列中,并依次执行。

2. 基于ScheduledExecutorService的实现

ScheduledExecutorService 是 Java 提供的另一个方法来实现延时任务。它更适合用来处理定时和周期性任务。

import java.util.concurrent.*;

public class ScheduledExecutorExample {
    public static void main(String[] args) {
        ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);

        Runnable task1 = () -> System.out.println("Task 1 executed at: " + new Date());
        Runnable task2 = () -> System.out.println("Task 2 executed at: " + new Date());

        // 延迟1秒执行
        scheduler.schedule(task1, 1, TimeUnit.SECONDS);
        // 延迟2秒执行
        scheduler.schedule(task2, 2, TimeUnit.SECONDS);

        scheduler.shutdown();
    }
}

在这个示例中,我们创建了一个 ScheduledExecutorService 实例,并使用 schedule 方法定义了延迟执行的任务。每个任务都会在指定的延迟后执行。

3. 自定义线程与时间轮算法

对于特定的高性能场景,可能需要自定义实现延时队列的逻辑,比如使用时间轮算法。这种方式比较复杂,但在某些场合下可以提高效率。

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

public class TimeWheel {
    // 时间轮的槽数量
    private final int wheelSize;
    private final ConcurrentHashMap<Long, Runnable> tasks = new ConcurrentHashMap<>();

    public TimeWheel(int wheelSize) {
        this.wheelSize = wheelSize;
    }

    public void addTask(long delay, Runnable task) {
        long executionTime = System.currentTimeMillis() + delay;
        tasks.put(executionTime, task);
    }

    public void start() {
        new Thread(() -> {
            while (true) {
                long currentTime = System.currentTimeMillis();
                tasks.forEach((time, task) -> {
                    if (time <= currentTime) {
                        task.run();
                        tasks.remove(time);
                    }
                });
                try {
                    TimeUnit.MILLISECONDS.sleep(100);
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                }
            }
        }).start();
    }
}

public class TimeWheelExample {
    public static void main(String[] args) {
        TimeWheel timeWheel = new TimeWheel(10);
        timeWheel.addTask(2000, () -> System.out.println("Task 1 executed at: " + new Date()));
        timeWheel.addTask(3000, () -> System.out.println("Task 2 executed at: " + new Date()));
        timeWheel.start();
    }
}

在这个示例中,我们实现了一个简单的时间轮,该轮会周期性检查任务并执行到期的任务。

总结

Java中有多种实现延时队列的方式,包括使用 DelayQueueScheduledExecutorService,以及自定义的时间轮算法。选择哪种实现方案取决于具体的业务需求和性能考虑。每种实现都有其适用场景,可以根据实际情况选择最优方案。

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部