BlockingQueueのドキュメントによると、一括操作はスレッドセーフではありませんが、drainTo() メソッドについては明示的に言及されていません。
BlockingQueue の実装はスレッドセーフです。すべてのキューイング メソッドは、内部ロックまたはその他の形式の同時実行制御を使用して、アトミックに効果を達成します。ただし、一括コレクション操作の addAll、containsAll、retainAll、および removeAll は、実装で特に指定されていない限り、必ずしもアトミックに実行されるとは限りません。そのため、たとえば、c の一部の要素のみを追加した後、addAll(c) が失敗する (例外がスローされる) 可能性があります。
drainTo() メソッドのドキュメントでは、BlockingQueue の要素が排出されるコレクションは、スレッドセーフな方法で変更できないことが指定されています。しかし、drainTo() 操作がスレッドセーフであることについては何も言及されていません。
このキューから使用可能なすべての要素を削除し、指定されたコレクションに追加します。この操作は、このキューを繰り返しポーリングするよりも効率的です。コレクション c に要素を追加しようとして失敗した場合、関連付けられた例外がスローされたときに、要素がどちらのコレクションにも含まれないか、いずれかのコレクションに含まれないか、または両方のコレクションに含まれない可能性があります。キューをそれ自体にドレインしようとすると、IllegalArgumentException が発生します。さらに、操作の進行中に指定されたコレクションが変更された場合、この操作の動作は未定義です。
では、drainTo() メソッドはスレッドセーフですか? 言い換えると、あるスレッドがブロッキング キューで drainTo() メソッドを呼び出し、別のスレッドが同じキューで add() または put() を呼び出している場合、両方の操作の終了時にキューの状態は一貫していますか?