Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/spring/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从另一个线程访问servlet范围的bean_Java_Spring_Servlets_Thread Safety - Fatal编程技术网

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

Java 从另一个线程访问servlet范围的bean,java,spring,servlets,thread-safety,Java,Spring,Servlets,Thread Safety,我使用的是来自“”答案的方法。然而,我看到很少有死锁涉及RequestAttributes对象。死锁的主要原因是对象中的synchronized(this.sessionattributesoupdate)语句和servlet会话哈希映射之间的死锁。通常为每个请求创建对象的实例,因此它们不会冲突,但是如果我将对象传递给另一个线程以使用会话bean,则会使用相同的对象,有时会导致死锁 如果当前http请求未完成,而另一个线程开始使用通过RequestContextHolder.setRequest

我使用的是来自“”答案的方法。然而,我看到很少有死锁涉及
RequestAttributes
对象。死锁的主要原因是对象中的
synchronized(this.sessionattributesoupdate)
语句和servlet会话哈希映射之间的死锁。通常为每个请求创建对象的实例,因此它们不会冲突,但是如果我将对象传递给另一个线程以使用会话bean,则会使用相同的对象,有时会导致死锁

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

我认为这家伙提到了同样的问题,但他的问题没有得到回答:


那么,如何避免死锁呢?

考虑到目标是在用户浏览页面时在后台计算一些内容,这里有一个答案提供了替代解决方案

可能性1: 使用@Async()注释的处理方法创建一个服务bean,该处理方法返回未来对象中的计算结果。在会话中存储未来对象。如果任务完成,则通过Future对象在后续请求中访问结果。通过Future取消任务。如果要在任务完成之前销毁会话,请取消

可能性2: 看看Spring 3.2和Servlet 3.0异步处理的新功能是否可以帮助您:

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

您能解释一下您在线程中做了什么吗?(也许你正试图解决的问题还有另一个解决方案)看看你发布的链接上的方法,我觉得这在逻辑上是错误的。特别是在请求/会话对象上调用set*方法的尝试,这些对象在被调用时可能不再存在。从后台线程访问会话中的对象对我来说似乎是一种错误的模式(但我可能弄错了)。@KresimirNesek当用户在页面之间导航时,线程会执行一些小型但耗时的后台工作来加载一些数据。一种预取机制。是的,我知道从http请求运行线程不是一件好事,但目前它是我们项目中唯一可行的解决方案。从请求启动线程是可以的,但我不知道直接使用会话是否是传输/同步参数和结果的好主意。当线程完成时,会话甚至可能不存在。无论如何,我在答案中发布了一些替代建议。希望有帮助@Kresimir:请注意,从请求启动非托管线程是绝对不行的。@BalusC同意。应该在评论中指出这一点。您知道异步调用是否会继承会话bean吗?而且,我需要从WS使用WorkManager,我不需要另一个线程池。2.据我所知,这是一个长时间运行的请求,我需要在请求之间做一些事情。3.对如果会话终止,则需要保持泄漏…1。这样看来是行不通的:(