0

優先度を維持しながら、オブジェクトのリストをスレッドセーフな方法で保存したいと考えています。もともと私はこれに BlockingQueue を使用し始めました。これは、スレッドセーフであり、カスタムの優先順位を維持する機能があるためです。

メソッドを同期する必要があるかどうか疑問に思っていますか? 私のコードは次のようになります:

void addToQueue(SomeObject obj) {
    ... put it on my priority queue
    ... do some logging
}

私が気付いたのは、複数のスレッドから addToQueue にアクセスするときに、ログが順不同で発生していることです。だから私は自分のメソッドを次のようにラップしました:

void addToQueue(SomeObject obj) {
    syncronized(myMutex) {
        ... put it on my priority queue
        ... do some logging
    }
}

これにより、ログが整然としているように見えました。したがって、このルートを使用する場合、BlockingQueue を使用せずに Set または List を使用して優先度を自分で管理することで、コードがより効率的になる可能性があるという結論に達しました。

BlockingQueue について誤解しているかもしれません。

4

2 に答える 2

1

要素を取得するときにキューが空でなくなるまで待機し、要素を格納するときにキューでスペースが使用可能になるまで待機する操作を追加でサポートする Queue 。

これは の javadoc ですBlockingQueue。このブロッキング動作が必要な場合はこれを使用し、そうでない場合は使用しません。

BlockingQueue優先度は維持されず、厳密に先入れ先出しです。おそらくあなたは使用していPriorityBlockingQueueますか?

あなたの疑似コードに来ます:

void addToQueue(SomeObject obj) {
    ... put it on my priority queue
    ... do some logging
}

キューはスレッド セーフですが、これは、複数のスレッドがput it on my priority queueデータを破損することなく同時に呼び出すことができることを意味するだけです。以下のことを保証するものではありません。

  • 複数のスレッドがブロックされている場合、どのスレッドが最初に成功するか
  • aがbefore をthread X完了する場合、 thenも before を完了します。putthread Ythread Xloggingthread Y

addToQueue他のスレッドからインターリーブせずにすべてを実行する必要がある場合は、同期する必要があります。キュー オブジェクト自体を使用できることに注意してください。

void addToQueue(SomeObject obj) {
    synchronized (queue) {
        ... put it on my priority queue
        ... do some logging
    }
}
于 2013-10-21T21:01:49.720 に答える
0

http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html

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

その安全性を使用して順序付けられたログを取得する場合は、アイテムをキューに入れる前とキューからアイテムを取得したにログを記録する必要があります。

synchronized順序付けられたログを取得するためには使用しません。マルチスレッドとは並列実行を意味し、特定のアクションに順序がないことを意味します。ログ レコードにはタイムスタンプが含まれている場合があり、コンソールでそれらを間違った順序で表示することは、並列実行の利点を犠牲にする価値のないマイナーな不具合のように見えます。

于 2013-10-21T20:59:42.887 に答える