我有一个没有保存按钮的应用程序;保存在后台自动发生。当用户使用应用程序时,会创建任务并将其放入队列中以供执行。其中一些是延迟的,例如,当你开始输入时,我等待200ms才更新数据库中的相应值。
为了使代码更简单,我希望能够通过延迟和“密钥”将任务添加到队列中。如果已经有一个具有相同“密钥”的任务,那么我的第二个任务应该被忽略(因为相同的操作已经排队)。
这样的事情已经存在吗?
答案 0 :(得分:3)
我认为你应该研究TreeMap课程。使用允许您传递Comparator的构造函数。这样你就可以让Map对Delayed进行排序(因为这个类实现了Comparable接口)。在向地图添加“任务”之前,使用containsKey方法检查密钥是否已存在。
答案 1 :(得分:1)
这就是我理解这个问题并接受挑战的方式:
任务包装器包装任务或命令,并添加其他值,任务的延迟和标识符。我明白,两个任务可能有相同的“密钥”,所以我们不能只接受任务哈希值。
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;
}
}
队列装饰器添加'set'之类的行为。队列没有'contains'方法,所以我需要一个额外的Set来记录实际被enqued的对象。将实现更改队列的所有方法以保持内部队列和集合之间的一致性。此快速草稿不是线程安全的,只显示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;
}
(可能充满了错误,我手头没有IDE。这只是一个草稿)
答案 2 :(得分:0)
我想到的优雅解决方案之一:使用一个具有priority blocking queue作为工作队列的线程池执行器。