0

私は、HTTP 経由でサーバー側にアクセスする Java クライアントを使用して、データの新しいページをロードするためのいくつかの小さな要求を作成しています。すべての非 UI 処理を処理するスレッド プールを維持しているため、バックグラウンドのクライアント側タスクとサーバーへの接続を必要とするタスクを処理します。いくつかのパフォーマンスの問題を調査してきましたが、スレッドプールが可能な限り適切に設定されているかどうか確信が持てません。現在、コア プール サイズが 8 の ThreadPoolExecutor を使用しています。ワーク キューには LinkedBlockingQueue を使用しているため、最大プール サイズは無視されます。間違いなく、すべての状況でこの特定のことを簡単に行うことはできませんが、ベストプラクティスはありますか. 現時点での私の考えは

1) LinkedBlockingQueue の代わりに SynchronousQueue を使用するように切り替えて、プールが最大プール サイズの数値まで拡大できるようにします。2) 最大プール サイズを無制限に設定します。

基本的に、私の現在の懸念は、サーバー側で時折発生するパフォーマンスの問題により、スレッド プール サイズの上限が原因で、関係のないクライアント側の処理が停止することです。制限を解除することに対する私の懸念は、クライアントでこれらのスレッドを管理する際の追加のヒットであり、おそらく 2 つの悪のうちの良い方です。

提案、ベスト プラクティス、または参考資料はありますか? 乾杯、ロビン

4

4 に答える 4

1

alphazeroが言ったように、ボトルネックがある場合、クライアント側の待機中のジョブの数は、使用するアプローチに関係なく増加し続けます。

問題は、ボトルネックにどのように対処するかです。より正確には、ユーザーにボトルネックにどのように対処してもらいたいかです。

無制限のキューを使用すると、ボトルネックが発生したというフィードバックは得られません。一部のアプリケーションでは、これで問題ありません。ユーザーが非同期タスクを開始している場合は、バックログを報告する必要はありません (最終的にはクリアされると仮定します)。ただし、ユーザーが次のクライアント側のタスクを実行する前に応答を待つ必要がある場合、これは非常に悪いことです。

制限付きキューで使用するLinkedBlockingQueue.offer()と、キューがいっぱいであることを示す応答がすぐに返され、特定のアプリケーション機能を無効にする、ダイアログをポップするなどのアクションを実行できます。ただし、特に複数の場所からリクエストを送信できる場合は、より多くの作業が必要になります。まだお持ちでない場合は、サーバー キュー上に GUI 対応レイヤーを作成して、一般的な動作を提供することをお勧めします。

そしてもちろん、LinkedBlockingQueue.put()イベント スレッドから呼び出してはいけません (クライアントのハングを気にしない限り)。

于 2009-12-16T13:44:45.047 に答える
1

一般に、ネットワーク遅延は、クライアント側でのメモリ割り当てまたはスレッド管理に関して発生する可能性のあるものよりも桁違いに高くなります。したがって、原則として、パフォーマンスのボトルネックに直面している場合は、何よりもまずネットワーク リンクを確認してください。

サーバーが単にクライアントからのリクエストに対応できないという問題がある場合、クライアント側でスレッドを増やしても問題は解決しません。8 つのスレッドが応答を待っている状態から、さらに多くのリクエストへの応答を待つことになります。待機中のスレッド (さらに、管理している接続数が多いために負荷が増加することにより、サーバー側の問題が悪化する可能性があります)。

JDK の同時キューは両方とも高性能です。選択は、実際には使用方法のセマンティクスに帰着します。ノンブロッキング プラミングがある場合は、ノンブロッキング キューを使用する方が自然です。そうでない場合は、ブロッキング キューを使用する方が理にかなっています。(いつでも制限として Integer.MAX_VALUE を指定できます)。FIFO 処理が必要でない場合は、公平な順序付けを指定しないようにしてください。これにより、パフォーマンスが大幅に低下します。

于 2009-12-16T12:45:54.913 に答える
1

キューのサイズを制限した方がよいように思えます: 多数のリクエストがキューに入れられている場合でも、アプリケーションは適切に動作しますか (すべてのタスクが長時間キューに入れられても問題ありませんか? キューに入れられたタスクがまだ残っていて、ユーザーがアプリケーションを終了するとどうなりますか? キューが非常に大きくなった場合、サーバーが (すぐに) 追いついて、ユーザーから問題を完全に隠す可能性はありますか?

ユーザー インターフェイスを更新するために応答が必要なリクエスト用に 1 つのキューを作成し、そのキューを非常に小さく保つことをお勧めします。このキューが大きくなりすぎた場合は、ユーザーに通知してください。

実際のバックグラウンド タスクの場合は、別のプールを保持します。キューは長くなりますが、無限ではありません。このプールが大きくなったとき、またはユーザーが終了したいがタスクが残っているときの適切な動作を定義します。どうすればよいですか?

于 2009-12-16T12:48:03.430 に答える
0

Why not create an unbounded queue, but reject tasks (and maybe even inform the user that the server is busy (app dependent!)) when the queue reaches a certain size? You can then log this event and find out what happened on the server side for the backup to occur, Additionally, unless you are connecting to a multiple remote servers there is probably not much point having more than a couple of threads in the pool, although this does depend on your app and what it does and who it talks to.

Having an unbounded pool is usually dangerous as it generally doesn't degrade gracefully. Better to log the problem, raise an alert, prevent further actions being queued and figure out how to scale the server side, if the problem is there, to prevent this happening again.

于 2009-12-16T12:07:24.960 に答える