需要混合使用延迟和地图

时间:2010-08-16 07:50:57

标签: java concurrency map delayed-execution

我有一个没有保存按钮的应用程序;保存在后台自动发生。当用户使用应用程序时,会创建任务并将其放入队列中以供执行。其中一些是延迟的,例如,当你开始输入时,我等待200ms才更新数据库中的相应值。

为了使代码更简单,我希望能够通过延迟和“密钥”将任务添加到队列中。如果已经有一个具有相同“密钥”的任务,那么我的第二个任务应该被忽略(因为相同的操作已经排队)。

这样的事情已经存在吗?

3 个答案:

答案 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作为工作队列的线程池执行器。