【问题标题】:Need a mix of Delayed and Map需要混合延迟和地图
【发布时间】:2011-03-30 07:38:06
【问题描述】:

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

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

类似的东西已经存在了吗?

【问题讨论】:

  • 只是为了澄清-您使用标准队列实现还是一些自定义数据结构?我们可以用所需的类似“Set”的行为来装饰吗?
  • 目前,我将更新添加到标准队列并启动计时器。当计时器用完时,我将整个队列推送到数据库并提交。现在我在想是否有更好/不同的方法。
  • 您是等到第一次按键后 200 毫秒,还是最后一次(最近)?还有一个有趣的问题——用例是什么?

标签: java concurrency map delayed-execution


【解决方案1】:

我想到的一个优雅的解决方案:使用具有priority blocking queue 作为工作队列的线程池执行器。

【讨论】:

  • 当我将相同的任务添加到队列时会发生什么?如果我对队列的理解正确,那么可能会有很多比较相等的任务。
  • 不保证具有相同优先级的元素的顺序。如果您需要强制执行排序,您可以定义自定义类或比较器,它们使用辅助键来打破主要优先级值的关系。
  • 延迟队列可能更合适吗?
【解决方案2】:

这就是我理解问题并接受挑战的方式:

任务包装器包装任务或命令并添加附加值、任务延迟和标识符。我明白了,两个任务可能有相同的“键”,所以我们不能只取任务的哈希值。

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,只是个草稿)

【讨论】:

    【解决方案3】:

    我认为您应该查看TreeMap 类。使用可让您传递比较器的构造函数。这样你就可以让 Map 对 Delayed 进行排序(因为这个类实现了 Comparable 接口)。在向地图添加“任务”之前,请使用 containsKey 方法检查键是否已存在。

    【讨论】:

    • 我认为这是最好的解决方案。队列不允许我摆脱重复的任务,所以我需要一个地图,或者可能需要一个 TreeMap 和一个 Set(这样我可以延迟排序 找到重复的键)。
    猜你喜欢
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多