33

私はJavaSEのバックグラウンドを持っており、サーブレットのチュートリアルをいくつか行い、Head First JSP&サーブレットを読みました。非同期サポートに関するJavaWorld.comの記事を読んでいますが、よくわかりません。

Asyncとは何ですか?Ajaxとサーブレット非同期の違いは何ですか?

PS私はajaxでPHPのバックグラウンドを持っていて、その概念を知っていますが、Javaで試したことはありません

4

1 に答える 1

84

従来のサーブレット モデルでは、1 リクエストが 1 スレッドに対応するのが通常でした。

これらのスレッドは通常、サーブレット コンテナーによって管理されるプールから取得されます。サーブレット コンテナは、このプールに空きスレッドがある限り、新しいリクエストのみを処理できます。独自のコードがリクエストの処理でビジーである限り、スレッドは解放されません。

状況によっては、このモデルを破る価値があるかもしれません。このようなサーブレット コンテナー管理スレッドを介してサーブレットにリクエストが到着すると、コードは非同期実行を要求します。その後、サーブレット リクエストから戻ることができ、コンテナ スレッドが解放されます。

同期リクエスト処理とは対照的に、これはレスポンスをコミットせず、接続を閉じません。代わりに、非同期コンテキストを別のスレッド プールに渡すことができます。別のスレッド プールはそれを取得できます。一部のスレッドがそれを処理できるようになったら、それを処理して、応答に書き込むことができます。

例:

@WebServlet(urlPatterns = "/somepath", asyncSupported = true)
public class AsyncServlet extends HttpServlet {

    @EJB
    private AsyncBean asyncBean;

    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        AsyncContext asyncContext = request.startAsync();

        // The following line will not block and return immediately
        asyncBean.doAsyncStuff(asyncContext);

    } // Shortly after this method has ended, thread will be returned to pool
}

次のAsyncBeanように実装されています。

@Stateless
public class AsyncBean {

    @Asynchronous
    public void doAsyncStuff(AsyncContext asyncContext) throws IOException {
        asyncContext.getResponse().getWriter().write("test");
    }
}

上記のコードでは、メソッドから戻った直後のどこかAsyncServlet#doGet()で、サーブレット スレッドがプールに返されます。実行するための「リクエスト」(タスク) はAsyncBean#doAsyncStuff()、EJB スレッド プールがピックアップするためにキューに入れられます。

これを使用する理由と時期に対する答えは、それほど単純ではありません。スレッドを保持したいだけの場合、上記のケースでは、あるスレッド プールのスレッドを別のスレッド プールと交換することになり (この場合はサーブレット プールと EJB 非同期プール)、純利益はそれほど多くありません。サーブレット スレッド プールに追加のスレッドを与えることもできます。

ただし、より高度なシナリオでは、リクエストをよりきめ細かく管理できます。それらを複数のタスクに分割し、それらのタスクにスレッド プール サービスを提供します。たとえば、10 MB のファイルに対する 100 のダウンロード リクエストが、ラウンド ロビンが各リクエストに一度に 100 KB を送信する 10 のスレッドによって処理されると想像してください。

さらに別のアプリケーションは、外部システムからのデータを待機する必要がある要求であり、この外部システムは、要求元に中継できるメッセージを送信できます。つまり、とにかく応答を待つ別のスレッドが必要になるため、データベース呼び出しはここでは意味がありません。次に、あるスレッドを別のスレッドに再度変更します。しかし、受信メールなどを待つ必要がある場合は、1 つのスレッドで任意のメールを待機し、それを保留中のリクエストに中継できます。

于 2012-04-08T20:52:13.583 に答える