我有一个没有保存按钮的应用程序;保存在后台自动发生。当用户使用应用程序时,会创建任务并将其放入队列中以供执行。其中一些是延迟的,例如,当您开始输入时,我会等待 200 毫秒,然后再更新数据库中的相应值。
为了使代码更易于使用,我希望能够将任务添加到队列中,并带有延迟和“键”。如果已经有一个具有相同“键”的任务,那么我的第二个任务应该被忽略(因为相同的操作已经排队)。
类似的东西已经存在了吗?
我有一个没有保存按钮的应用程序;保存在后台自动发生。当用户使用应用程序时,会创建任务并将其放入队列中以供执行。其中一些是延迟的,例如,当您开始输入时,我会等待 200 毫秒,然后再更新数据库中的相应值。
为了使代码更易于使用,我希望能够将任务添加到队列中,并带有延迟和“键”。如果已经有一个具有相同“键”的任务,那么我的第二个任务应该被忽略(因为相同的操作已经排队)。
类似的东西已经存在了吗?
我认为您应该研究TreeMap类。使用可让您传递比较器的构造函数。这样你就可以让 Map 对 Delayed 进行排序(因为这个类实现了 Comparable 接口)。在向地图添加“任务”之前,使用 containsKey 方法检查键是否已存在。
这就是我理解这个问题并接受挑战的方式:
任务包装器包装任务或命令并添加附加值、任务延迟和标识符。我明白,两个任务可能有相同的“键”,所以我们不能只取任务哈希值。
public TaskWrapper<T> {
private T task;
private long delayInMillis;
private long key;
public TaskWrapper(T task, long delayInMillis, long key) {
this.task = task;
this.delayInMillis = delayInMillis;
this.key = key;
}
// getter, setters, and so on
public boolean equals(Object o) {
if (o == null || !(o instanceof TaskWrapper)) return false;
return key == ((TaskWrapper) o).key;
}
}
队列装饰器添加了类似“集合”的行为。队列没有 'contains' 方法,所以我需要一个额外的 Set 来记录实际排队的对象。所有改变队列的方法都将被执行以保持内部队列和集合之间的一致性。此快速草稿不是线程安全的,仅显示add
方法。
public SetQueue<TaskWrapper> implements Queue<T> {
private Queue<TaskWrapper> queue;
private Set<TaskWrapper> set = new HashSet<TaskWrapper>();
public SetQueue(Queue<TaskWrapper> queue) {
this.queue = queue;
}
// just to demonstrate the idea
public boolean add(TaskWrapper<?> task) {
if (set.contains(task)
return false;
boolean result = queue.add(task);
if (result)
set.add(task);
return result;
}
(可能有很多bug,我手头没有IDE,只是个草稿)
我想到的优雅解决方案之一:使用具有优先阻塞队列作为工作队列的线程池执行器。