3

保存ボタンのないアプリケーションがあります。保存はバックグラウンドで自動的に行われます。ユーザーがアプリを操作すると、タスクが作成され、実行のためにキューに入れられます。それらのいくつかは遅れています。たとえば、入力を開始すると、データベース内の対応する値を更新する前に200ミリ秒待機します。

これをコード的に使いやすくするために、遅延と「キー」を使用してタスクをキューに追加できるようにしたいと思います。同じ「キー」を持つタスクがすでに存在する場合は、2番目のタスクを無視する必要があります(同じ操作がすでにキューに入れられているため)。

そのようなものはすでに存在しますか?

4

3 に答える 3

3

TreeMapクラスを調べる必要があると思います。コンパレータを渡すことができるコンストラクタを使用します。このようにして、MapをDelayedでソートさせることができます(このクラスはComparableインターフェイスを実装しているため)。マップに「タスク」を追加する前に、containsKeyメソッドを使用してキーがすでに存在するかどうかを確認してください。

于 2010-08-16T08:04:24.760 に答える
1

これが私が質問を理解し、挑戦する方法です:

タスクラッパーは、タスクまたはコマンドをラップし、追加の値、タスクの遅延、および識別子を追加します。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;
  }

(バグでいっぱいかもしれません、私は手元にIDEを持っていません。それは単なるドラフトです)

于 2010-08-16T15:02:01.733 に答える
0

私の頭に浮かんだエレガントなソリューションの1つは、優先度ブロックキューを持つスレッドプールエグゼキュータを作業キューとして使用することです。

于 2010-08-20T16:48:11.450 に答える