5

ArrayBlockingQueue は、キューがいっぱいの場合はプロデューサー スレッドをブロックし、キューが空の場合はコンシューマー スレッドをブロックします。

このブロッキングの概念は、マルチスレッドの考え方そのものに反するのではないでしょうか? 「メイン」スレッドがあり、すべての「ロギング」アクティビティを別のスレッドに委任したいとします。したがって、基本的にメインスレッド内で、Runnable を作成して出力をログに記録し、Runnable を ArrayBlockingQueue に配置します。これを行う全体的な目的は、高価なロギング操作で時間を無駄にすることなく、「メイン」スレッドをすぐに返すことです。

ただし、キューがいっぱいの場合、メイン スレッドはブロックされ、スポットが利用可能になるまで待機します。それで、それはどのように私たちを助けますか?

4

8 に答える 8

9

キューはそれにもかかわらずブロックするのではなく、システムに追加の品質を導入するためにブロックします。この場合、飢餓の防止です

一連のスレッドを想像してみてください。そのうちの 1 つが作業単位を非常に高速に生成します。キューが無制限に増加することを許可する場合、潜在的に、「急速なプロデューサー」キューがすべての生産能力を独占する可能性があります。場合によっては、すべてのスレッドのブロックを解除するよりも、このような副作用を防止する方が重要です。

于 2013-07-05T18:33:38.217 に答える
3

あなたの例では、ブロッキングを機能と見なします。OutOfMemoryError を防ぎます。

一般的に言えば、スレッドの 1 つが、割り当てられた負荷に対応するには十分に高速ではありません。したがって、アプリケーション全体を危険にさらさないようにするために、他のものは何らかの方法で速度を落とさなければなりません。

一方、負荷が分散されている場合、キューはブロックされません。

于 2013-07-05T18:34:59.347 に答える
1

それは、マルチスレッドの哲学の性質に依存します。シーケンシャル プロセスの通信を好む私たちにとって、ブロッキング キューはほぼ完璧です。実際、理想は、受信者がそれを受信する準備ができていない限り、メッセージをまったくキューに入れることができないものです。

いいえ、ブロッキングキューがマルチスレッドの目的に反するとは思いません。実際、あなたが説明したシナリオ (メイン スレッドが最終的に停止する) は、マルチスレッドのアクター モデルの主要な問題をよく表しています。デッドロック/ブロックするかどうかはわかりませんし、徹底的にテストすることもできません。

対照的に、メッセージの深さがゼロのブロッキング キューを想像してみてください。システムがまったく機能するようにするには、ロガーがメインスレッドからメッセージを受信できることが常に保証されるようにする方法を見つける必要があります。それがCSPです。仮想ロガー スレッドでは、アプリケーション定義のバッファリング (FIFO の深さについてのフレームワーク開発者の最善の推測とは対照的に)、高速 I/O サブシステム、追いつくためのチェック、対処方法が必要であることを意味する場合があります。つまり、システムのパフォーマンスのあらゆる側面に対処する必要があります。

もちろんそれは難しいことですが、そうすれば、ブロッキング キューが不明な数のメッセージの深さである場合に発生する疑わしい「多分」ではなく、間違いなく問題のないシステムになります。

于 2013-07-05T19:04:12.807 に答える
0

マルチスレッド プログラムは、事前に断言できない限り、非決定論的です。n プロデューサー アクションは、m コンシューマー アクションとまったく同じ時間かかります。したがって、n 個のプロデューサと m 個のコンシューマの間の同期は、すべての場合に必要です。

ほとんどの場合、アクティブなプロデューサーとコンシューマーの数が最大になるように、キューのサイズを選択する必要があります。しかし、Java のスレッド モデルは、ブロックされていない唯一のスレッドでない限り、コンシューマが実行されることを保証しません。(ただし、もちろん、マルチコア CPU では、コンシューマが実行される可能性が非常に高くなります)。

于 2013-07-05T18:39:29.187 に答える