0

我有一个需要 50 秒来处理的大动作。但是,与此同时,我还有另一个可以在服务器上处理的操作(通过单击链接)。

但是,如果我的第二个操作尝试访问我的第一个操作放置的会话属性,则它们在第一个操作结束之前可用。

这是我的大动作:

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;
}
第一个动作:---------------------------------------------------------

第二个动作: --- -- --- - ---

因此,在此示例中,我的第二个操作需要由第一个操作创建的会话属性,但实际上它们并不存在。

如何同步我的会话?

4

2 回答 2

2

根据 Servlet 规范:

多个执行请求线程的 servlet 可以同时对同一个会话对象进行主动访问。容器必须确保以线程安全的方式执行表示会话属性的内部数据结构的操作。开发人员负责对属性对象本身进行线程安全访问。这将保护 HttpSession 对象内的属性集合免受并发访问,从而消除应用程序导致该集合损坏的机会。

这是安全的:

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

这不能保证是安全的:

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

此外,如果在同一个对象上,锁将起作用,不要依赖于request.getSession()返回相同的对象。Servlet 规范中没有任何内容说HttpServletSession每次请求实例时都不能将其重新创建为外观对象。

阅读Java 理论与实践:所有有状态的 Web 应用程序都损坏了吗?以及HttpSession 如何不是线程安全的。

这里定义了一种方法,Java-synchronizing-on-transient-id

于 2013-07-15T13:28:13.463 回答
0

今天的变化:

我正在使用 Struts 2,所以我实现了 SessionAware,因为我读到它可能是一个很好的解决方案。但这是一样的。

于 2013-07-18T14:59:08.253 回答