异步处理=生成线程=有效吗?

时间:2010-05-11 18:22:44

标签: java servlets concurrency

我是否允许(没有任何副作用)从servlet的new Thread()内创建并启动doGet() Method?或者这会以某种方式泄漏资源?

将“Session”对象传递给线程以便稍后在会话中保存我的异步处理结果(我会正确同步)是否有效?或者,当使用会话“in indepedant threads”时,这个泄漏会重新获得资源吗?

=>如果会话同时会被webcontainer过期,因为它有timedout并且我将从我的线程访问它会发生什么?或者这也会导致副作用,将会话存储在线程中会阻止web容器到期会话(因此最终会泄漏资源,因为会话没有被清除)?

(我知道还有其他解决方案,比如使用DB-(Job)Records,JMS或Servlets 3.0)但我需要解决问题,如在doGet中跨越一个新线程所描述的那样。)

非常感谢!! 延

4 个答案:

答案 0 :(得分:0)

从servlet中创建新线程被认为是不好的做法。产生新线程的常用替代方法是使用JMS / MDB进行异步处理。

答案 1 :(得分:0)

虽然被认为是不好的做法,但它适用于小规模项目。更好的解决方案是使用ExecutorService来执行工作(即使您创建了一个包含ExectorService的单例)。这种方法应该与应用程序服务器提供的线程池一致(尽管我没有尝试过)。

从servlet中执行以下操作:

Future future = myExecutorService.submit(new Task(workRequest));
session.put("result", future);

我也不会将用户Session对象传递给服务,因为会话的实现可能涉及ThreadLocal。而是执行程序生成一个Future对象,您可以将其放入会话中。这样,您可以测试以查看您的异步计算是否稍后完成(或取消或等待它)。

Future future = session.get("result");
boolean isDone = future.isDone();
boolean isCancelled = future.isCancelled();
showInJSP(isDone, isCancelled);

答案 2 :(得分:0)

首先,您想要做的事情将是可行的。取决于一大堆事情。但是如果系统负载很小,请求很少等,它可能会正常工作。

关于您的会话过期问题,赔率是“什么都不会发生”。您将很乐意存储和引用其他人无法查看的信息。

天真地,服务器将使会话到期,并从其内部映射中删除Session对象。与此同时,您的主题将保留对它的引用,并且不会更清楚会话是好还是坏。

在加载的服务器上,系统可能会获取用户会话信息并将其序列化为磁盘。当用户回来时,它会重新读回来。在这种情况下,你将指的是“旧的,孤儿”会话,再次,用户将再也看不到。

当你的线程死亡时,Session将随线程一起离开。

所以,基本上,只要你有一个服务器实例,你没有集群,你的服务器没有交换会话,服务器不会重启(这是另一个点,

。服务器可能会保存和恢复会话,并且会话不会超时 - 你应该很好。

是的,这些都是对你的技术的限制,它不会使技术错误,它只是限制了实现。如果您的应用程序和服务在这些限制条件下可以正常工作,那么您就会很高兴,并且不用担心它。

答案 3 :(得分:0)

  

我是否允许(没有任何副作用)从servlet的doGet()方法中创建并启动一个新的Thread()?

如果实施得当,这很好。

  

将“Session”对象传递给线程以便稍后在会话中保存我的异步处理结果(我会正确同步)是否有效?

我不会这样做。而是将Thread存储在会话中。通过这种方式,您可以随时在需要时将其收回。

  

如果会话同时会被webcontainer过期,因为它有timedout并且我将从我的线程访问它会发生什么?或者这也会导致副作用,将会话存储在线程中会阻止web容器到期会话(因此最终会泄漏资源,因为会话没有被清除)?

会话将过期(如果您在Thread在其中保留对它的引用,则会GC),但该线程将继续运行,直到从{{返回} 1}}方法。通常的做法是在run()方法中定期检查你自己(如果线程中断或不中断)(例如,在每个步骤或每1%进度期间一次)。您可以实现HttpSessionBindingListener以在会话过期时发出中断信号。

run()