0

処理に 50 秒かかる大きなアクションがあります。しかし、同時に、サーバー上で (リンクをクリックすることで) 処理できる別のアクションがあります。

ただし、2 番目のアクションが最初のアクションによって設定されたセッションの属性にアクセスしようとすると、それらは最初のアクションが終了するまで利用できません。

これは私の大きな行動です:

public String bigAction() {
    HttpSession session = request.getSession();
    synchronized (session) {
        for(int i = 0 ; i < 100000 ; ++i)
             session.setAttribute("foo_"+i, "bar");
        }
    return SUCCESS;
}

そして、これは私の小さなアクションです:

public String smallAction() {
    HttpSession session = request.getSession();
    synchronized (session) {
        session.getAttribute("foo_1", "bar");
    }
    return SUCCESS;
}
最初のアクション: ---------------------------------------------------

2 番目のアクション: --- -- --- - ---

したがって、この例では、2 番目のアクションは最初のアクションによって作成されたセッションの属性を必要としますが、実際には存在しません。

セッションを同期するにはどうすればよいですか?

4

2 に答える 2

2

サーブレット仕様によると:

要求スレッドを実行する複数のサーブレットは、同じセッション オブジェクトに同時にアクティブにアクセスできます。コンテナーは、セッション属性を表す内部データ構造の操作がスレッドセーフな方法で実行されるようにする必要があります。開発者は、属性オブジェクト自体へのスレッドセーフ アクセスを担当します。これにより、HttpSession オブジェクト内の属性コレクションが同時アクセスから保護され、アプリケーションがそのコレクションを破損させる可能性がなくなります。

これは安全です:

request.getSession().setAttribute("bar", "foo");

これは安全であるとは限りません:

HttpSession session = request.getSession();
synchronized (session) {
   String value = (String) session.getAttribute("bar");
}

request.getSession()さらに、同じオブジェクトの場合、ロックは機能します。同じオブジェクトを返すことに依存しないでください。サーブレット仕様には、HttpServletSessionインスタンスが要求されるたびにインスタンスをファサード オブジェクトとして再作成できないと言うものは何もありません。

Java の理論と実践を読んでください: ステートフルな Web アプリケーションはすべて壊れていますか? およびHttpSession がスレッドセーフではない方法

アプローチの 1 つはここで定義されているJava-synchronizing-on-transient-idです。

于 2013-07-15T13:28:13.463 に答える