从另一个线程访问servlet范围的bean

时间:2013-04-02 15:51:30

标签: java spring servlets thread-safety

我正在使用“Accessing scoped proxy beans within Threads of”答案中的方法。但是我看到涉及RequestAttributes对象的罕见死锁。死锁的主要原因是对象中的synchronized (this.sessionAttributesToUpdate)语句和servlet会话哈希映射之间。通常,为每个请求创建对象的实例,因此它们不会发生冲突,但如果我将对象传递给另一个线程以使用会话bean,则会使用相同的对象,并且有时会导致死锁。

如果当另一个线程开始使用与RequestContextHolder.setRequestAttributes一起传递的会话bean时,当前的http请求未完成,则会发生死锁。

我认为这个人提到同样的问题,但他的问题没有答案:Session scoped bean encountering deadlock

那么,任何想法如何避免死锁?

1 个答案:

答案 0 :(得分:0)

这是一个提供替代解决方案的答案,考虑到目标是在用户导航页面时计算背景中的内容。

可能性1: 使用带有@Async(http://static.springsource.org/spring/docs/3.0.x/reference/scheduling.html)注释的处理方法创建服务bean,该方法返回Future对象中的计算结果。将Future对象存储在会话中。如果任务完成,则通过Future对象访问后续请求中的结果。如果要在任务完成之前销毁会话,则通过Future.cancel取消任务。

可能性2: 看看Spring 3.2和Servlet 3.0异步处理的新功能是否可以帮助您: http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/mvc.html#mvc-ann-async

可能性3: 模拟任务队列。创建一个单例服务,可以将对象放置到像ConcurrentMap这样的结构中,其中key是某个作业ID(您可以将键存储到会话中)并重视后台处理的结果。然后后台线程会在那里存储对象(这可能不比直接访问会话好多少,但你可以确保它的线程安全)。