いいえ、メソッドを同期する必要はなく、メソッドを定義する必要もありません。それらはすでにConcurrentLinkedQueueにあります、それらを使用してください。ConcurrentLinkedQueueは、内部で必要なすべてのロックおよびその他の操作を実行します。プロデューサーがキューにデータを追加し、コンシューマーがそれをポーリングします。
まず、キューを作成します。
Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();
ここで、プロデューサー/コンシューマーオブジェクトを作成する場所にキューを渡して、オブジェクトをどこかに配置できるようにします(代わりにセッターを使用できますが、コンストラクターでこの種のことを行うことをお勧めします)。
YourProducer producer = new YourProducer(queue);
そして:
YourConsumer consumer = new YourConsumer(queue);
そして、あなたのプロデューサーでそれにものを追加します:
queue.offer(myObject);
そして、コンシューマ内のものを取り出します(キューが空の場合、poll()はnullを返すので、チェックしてください)。
YourObject myObject = queue.poll();
詳細については参照してください 、Javadocを
編集:
キューが空になるのを待つのをブロックする必要がある場合は、おそらくLinkedBlockingQueueを使用する必要がありますを使用して、take()メソッドがあります。ただし、LinkedBlockingQueueには最大容量(デフォルトではInteger.MAX_VALUE、20億を超える)があるため、状況に応じて適切な場合とそうでない場合があります。
キューにデータを入れるスレッドが1つだけで、キューからデータを取り出す別のスレッドがある場合、ConcurrentLinkedQueueはおそらくやりすぎです。数百または数千のスレッドが同時にキューにアクセスする可能性がある場合に適しています。あなたのニーズはおそらく以下を使用することで満たされます:
Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());
さらに、インスタンス(キュー)でロックされるため、キューで同期して、複合操作のアトミック性を確保できます(Jaredが説明)。すべての操作はインスタンスのロックなしで(java.util.concurrent.atomic変数を使用して)実行されるため、これをConcurrentLinkedQueueで行うことはできません。キューが空のときにブロックしたい場合は、これを行う必要はありません。なぜなら、poll()は、キューが空のときにnullを返すだけで、poll()はアトミックだからです。poll()がnullを返すかどうかを確認します。存在する場合は、wait()してから、再試行してください。ロックする必要はありません。
最後に:
正直なところ、私はLinkedBlockingQueueを使用します。それはあなたのアプリケーションにとってはまだやり過ぎですが、おそらくうまくいくでしょう。十分なパフォーマンスがない場合(プロファイル!)、いつでも別の方法を試すことができます。これは、同期されたものを処理する必要がないことを意味します。
BlockingQueue<YourObject> queue = new LinkedBlockingQueue<YourObject>();
queue.put(myObject); // Blocks until queue isn't full.
YourObject myObject = queue.take(); // Blocks until queue isn't empty.
他はすべて同じです。20億個のオブジェクトをキューに入れる可能性は低いので、Putはおそらくブロックしません。