21

サーブレットAPIは「AsyncContext.start」について次のように述べています。

void start(java.lang.Runnable run)

コンテナに、おそらく管理対象スレッドプールからスレッドをディスパッチさせて、指定されたRunnableを実行させます。コンテナは、適切なコンテキスト情報をRunnableに伝播する場合があります。

この説明から、ジョブが待機を必要とするときにスレッドの使用を最適化するタスクにどのように関連するかは明確ではありません。

「サーブレットとJSP」では、Budi Kurniawanがサーブレット3.0非同期機能の例をAsyncContext.start示しています。彼が使用している例では、例の簡略版を示します。

public void doGet(...) {
    final AsyncContext asyncContext = request.startAsync();

    asyncContext.start(new Runnable() {                        
        @ Override
        public void run() {
            // do some work here which involves waiting
            ...
            asyncContext.complete();
        }
    });
}

私が出会った他のほとんどの例では、サービスメソッドはAsyncContextをどこかに格納し、別の場所で処理されます(たとえば、バックグラウンドスレッドによって)。この例では、ジョブが別のスレッドに渡され、リクエストが完了したように見えます。私が理解しているように、今では単にワーカースレッドであり、待機に時間を浪費しています。

あるスレッドから別のスレッドにジョブ(待機を含む)を渡すことによって、実際に何かを得ることができますか?そうでない場合、その目的はAsyncContext.start(...)何ですか?

4

4 に答える 4

18

あなたは悪い例を見つけました、IMHO。実は存在すら知らなかっAsyncContext.start()た。

JettyTomcatがこれをどのように実装しているかを簡単に見てみました。実際、非同期呼び出しを個別に処理するスレッド プールがいくつかあるようです。

このような API の使用では、何も得られないか、ほとんど得られません。HTTP スレッドをブロックする代わりに、他のスレッド プールをブロックしています。したがって、アプリケーションはまだ新しい接続を受け入れると想像できますが、問題は残ります。余分なスレッド プールがまだ限られているため、コンテナーはすべての接続を処理できません。

の要点はAsyncContext、単一のスレッドで複数の要求を処理できることです。多くの場合、数千の非同期接続を処理するのに 1 つのスレッドしか必要ありません。たとえば、複数のクライアントにブロードキャストされると思われるデータをちょうど 1 つのスレッドが待機している場合などです。AsyncContext.start() の限定的な有用性も参照してください。

于 2012-04-09T13:07:45.277 に答える
13

私も最初は同じ反応を示しました。作業を別のスレッドに渡すだけだとしたら、何の得があるのでしょうか。仕様は、これが良いアイデアである理由を説明するのにあまり役に立ちません。しかし、この投稿は素晴らしい仕事をしています。基本的には、スレッドが不足してサーバーが機能しなくなるのではなく、負荷が高い場合にサーバーを適切に機能低下させるためです。実際の作業は固定サイズのスレッド プールで行われるため、サーバーは要求が完了するまでそれぞれのスレッドを維持する必要なく、任意の数の要求を受け入れることができます。もちろん、一度に何千ものソケットを開いたままにできるように、O/S 設定を微調整する必要があるかもしれません。

この機能があれば、Comet (サーバー プッシュ) アーキテクチャをより簡単に利用できます。このアーキテクチャでは、クライアントの Javascript が AJAX 要求を開いたままにして、イベントが発生するとすぐにサーバーが通知できるようにします。何かが起こったかどうかを調べるためのサーバー。

于 2012-06-07T14:20:37.583 に答える
0

これが役立つ理由の 1 つは、着信 Web スレッドを解放し、他の作業を行い、完了後に Web スレッド (別のスレッドである可能性がありますが、Web サーバー プールから) に戻って元のスレッドを完了する場合です。操作を行い、クライアントに応答を送信します。

例えば:

1. ac = request.startAsync();
2. forward("some data", "another system"); // async outbound HTTP request
3. (at this point, incoming servlet thread is released to handle other requests)
4. (in some other, non-servlet thread, upon "forward" response arrival)
   ac.start(new Runnable() { /* send response to the client */ });

もちろん、非サーブレット スレッドで応答を送信することもできますが、これには 1 つの欠点があります。非サーブレット スレッドを使用してサーブレットの典型的な操作を実行します。サーブレット作業とその他の作業。

つまり、Runnable をサーブレット スレッド プールにポストできるようになります。明らかに、これらはめったに必要ではありませんが、それでも - AsyncContext.start() メソッドに何らかの理由を与えます。

于 2014-07-10T21:15:33.503 に答える