1

アイテムのキューで長時間実行プロセスを開始しています。アイテムが処理されるようにスケジュールされているか、処理されている間、他の操作を禁止したいと考えています。私のコードは基本的に次のようになります。

public class LongRunningProcess extends Thread {
    private final ConcurrentLinkedQueue<Item> pending = new ConcurrentLinkedQueue<>();
    private final Set<Item> active = Collections.newSetFromMap(new ConcurrentHashMap<Item, Boolean>());

    public LongRunningProcess() {
        // add items to pending; no more items will ever be added
    }

    @Override
    public void run() {
        while (! pending.isEmpty()) {
            // The peek/add/remove pattern here is important. The number
            // of items that are active or scheduled is always decreasing.
            // Because isScheduled checks pending before checking active,
            // this order of operations ensures that we never miss an item
            // as it is being switched from one collection to the other.
            Item nextItem = pending.peek();
            active.add(nextItem);    // <---Can any of these get reordered?
            pending.remove();        // <---+
            processItem(nextItem);   // <---+
            active.remove(nextItem); // <---+
        }
    }

    public boolean isScheduled(Item item) {
        return pending.contains(item) || active.contains(item);
    }
}

これは期待どおりに機能しますか、それとも上記の強調表示されたコード ブロックの順序を変更することはできますか? 関連する仕様を教えてください。

編集:

@Banthar の有益なコメントは、私の質問に明確に答えるjava.util.concurrent パッケージのドキュメントに私を導きました:

およびそのサブパッケージのすべてのクラスのメソッドは、java.util.concurrentこれらの保証をより高いレベルの同期に拡張します。特に:

  • オブジェクトを並行コレクションに配置する前のスレッド内のアクションは、別のスレッド内のコレクションからのその要素へのアクセスまたは削除に続くアクションの前に発生します。
4

1 に答える 1