2016-04-18 25 views
5

私はCollections.Synchronizedlist()を使用して、arraylistをスレッドセーフにしています。私がお聞きしたいのは端からリストを反復処理しながら、すなわち削除し、次のコードをスレッドセーフである: -Collections.synchronizedlist()は、反復処理中に要素を削除します。

pendingExecutionList = Collections.synchronizedList(new ArrayList<>(initialCapacity)); 

私はメインスレッドでリストを作成しています。異なるスレッドからこのリストに追加します。しかし、反復及び除去以下に示すように、単一のスケジュールスレッドから行われている: -

for (int i = pendingExecutionList.size() - 1; i >= 0; i--) 
{ 
    if (someCondition(pendingExecutionList.get(i))) 
    { 
     process(pendingExecutionList.remove(i)); 
    } 
} 

複数のスレッドがこのリストに追加されている間、上記のコードは、単一のスレッドによって実行されます。

synchronized(list)以上の反復子は、フェイルセーフではないので、使用しないでください。

+2

答えはhttp://stackoverflow.com/questions/9468187/collections-synchronizedlist-and-synchronized – alphablue

+2

にあります。いいえ、スレッドセーフではありません。[The javadoc](http://docs.oracle.com/jp/) com/javase/8/docs/api/java/util/Collections.html#synchronizedList-java.util.List-)は非常に明確です:*ユーザが反復処理をするときに返されたリストを手動で同期させることが不可欠です*。 –

+0

なぜですか? – maveroid

答えて

1

ワークフローのパイプラインを正しく理解している場合は、synchronizedList()の代わりにBlockingQueueのいくつかの変形を試すことをおすすめします。

ArrayBlockingQueue実行の公平なスケジューリングを可能にし、複数のプロデューサのキャッシュをかなり高温に保つ必要があります(プロデューサがキャッシュプリフェッチャーを追い抜かない場合は、誤った共有が発生します)。

実験の気分があれば、Nitsan WakartのMpscArrayQueueまたはDisruptorのように、JDKの外部で利用可能なMPSC(複数のプロデューサ、単一消費者)キューを見ることができます。

+0

しかし、リストのサイズは固定されていません。それは成長することができます。 BlockingQueueのどのバリアントを好きですか? – maveroid

+1

モバイル環境または組み込み環境向けに開発していない場合は、アプリケーションの起動時に適切なバッファを割り当てることができる可能性があります。 Martin Thompson(機械的共感者/ Disruptorの一員)のように、無制限の待ち行列は、システムをメモリから奪うことのできるバンドエイドとしてよく使われます(http:// mechanical-sympathy参照)。blogspot.bg/2012/05/apply-back-pressure-when-overloaded.html)。それでも、無制限のキューを使うほうが良いと思えば、 'LinkedBlockingQueue'か非ブロック化' ConcurrentLinkedQueue'を試すことができます。 –

2

ロックを保持する代わりに、要素ごとにロックを実際に取得しています。これは、小切手をしている間だけロックを保持するよりも遅くなるリスクがあります。

PriorityQueueを適切な順序で使用することをお勧めします。これにより、次に処理する予定のものが開始時に表示され、待機中のタスクの数に関係なく、削除のコストは比較的安くなるように、キューが順序付けされます。

+0

私はどこにでもロックしていません。説明できますか? – maveroid

+0

@maveroid 'Collections.synchronizedList'メソッドを使用していて、すべてのメソッドが同期されている場合、あなたはそれを認めるかどうかに関わらずロックを使用しています;) –

+0

いいえ、ロックは追加されています)、remove()を繰り返さないでください。右? – maveroid

関連する問題