Java 异步处理=跨越线程=有效?
是否允许我(没有任何副作用)从servlet的Java 异步处理=跨越线程=有效?,java,servlets,concurrency,Java,Servlets,Concurrency,是否允许我(没有任何副作用)从servlet的doGet()方法中创建并启动new Thread()?还是这会泄露资源 将“Session”对象传递到线程中,以便稍后在会话中保存异步处理的结果(我将正确同步)是否有效?或者在“独立线程”中使用会话时会泄漏资源 =>如果会话同时被webcontainer终止,因为它有timedout,我将从我的线程访问它,会发生什么?或者,这是否也会导致副作用,即将会话存储在线程中会阻止webcontainer终止会话(因此最终会泄漏资源,因为会话未被清除) (我
doGet()方法中创建并启动new Thread()
?还是这会泄露资源
将“Session
”对象传递到线程中,以便稍后在会话中保存异步处理的结果(我将正确同步)是否有效?或者在“独立线程”中使用会话时会泄漏资源
=>如果会话同时被webcontainer终止,因为它有timedout,我将从我的线程访问它,会发生什么?或者,这是否也会导致副作用,即将会话存储在线程中会阻止webcontainer终止会话(因此最终会泄漏资源,因为会话未被清除)
(我知道还有其他解决方案,比如使用DB-(作业)记录、JMS或Servlets 3.0),但我需要通过在doGet中跨一个新线程来解决问题。)
非常感谢!!
Jens从servlet中创建新线程被认为是不好的做法。生成新线程的常用替代方法是使用JMS/MDB进行异步处理。从servlet中创建新线程被认为是不好的做法。产生新线程的常用替代方法是使用JMS/MDB进行异步处理。虽然被认为是不好的做法,但它适用于小规模项目。更好的解决方案是使用ExecutorService来执行工作(即使您创建了一个保存ExecutorService的单例)。这种方法应该与ApplicationServer提供的线程池一致(尽管我没有尝试过)
在servlet中执行以下操作:
Future future = myExecutorService.submit(new Task(workRequest));
session.put("result", future);
我也不会将用户会话对象传递给服务,因为会话的实现可能涉及ThreadLocal。相反,执行器生成一个未来对象,您可以将其放入会话中。这样,您就可以测试异步计算是否稍后完成(或者取消或等待)
虽然被认为是不好的做法,但它适用于小规模项目。更好的解决方案是使用ExecutorService来执行工作(即使您创建了一个保存ExecutorService的单例)。这种方法应该与ApplicationServer提供的线程池一致(尽管我没有尝试过)
在servlet中执行以下操作:
Future future = myExecutorService.submit(new Task(workRequest));
session.put("result", future);
我也不会将用户会话对象传递给服务,因为会话的实现可能涉及ThreadLocal。相反,执行器生成一个未来对象,您可以将其放入会话中。这样,您就可以测试异步计算是否稍后完成(或者取消或等待)
首先,你想做的可能会奏效。取决于一大堆事情。但是对于一个负载小、请求少等的系统,它可能工作得很好
关于会话到期问题,可能性是“什么也不会发生”。您将很高兴地存储和引用其他人看不到的信息
很自然,服务器将使会话过期,并从其内部映射中删除会话对象。同时,您的线程将保留对它的引用,并且不会更明智地判断会话是好是坏
在已加载的服务器上,系统可能会获取用户会话信息并将其序列化到磁盘。当用户返回时,它会将其读入。在这种情况下,您将引用“旧的、孤立的”会话,用户将再也看不到该会话
当线程死亡时,会话将随线程一起消失
因此,基本上,只要您有一个服务器实例,您没有集群,您的服务器没有交换会话,服务器没有重新启动(这是服务器可能保存和恢复会话的另一个点),并且会话没有超时,您就应该做得很好
是的,这些都是对您的技术的限制,它不会使技术出错,它只是限制了实现。如果您的应用程序和服务能够在这些限制条件下正常工作,那么您就是黄金,不用担心。首先,您想做的事情可能会成功。取决于一大堆事情。但是对于一个负载小、请求少等的系统,它可能工作得很好
关于会话到期问题,可能性是“什么也不会发生”。您将很高兴地存储和引用其他人看不到的信息
很自然,服务器将使会话过期,并从其内部映射中删除会话对象。同时,您的线程将保留对它的引用,并且不会更明智地判断会话是好是坏
在已加载的服务器上,系统可能会获取用户会话信息并将其序列化到磁盘。当用户返回时,它会将其读入。在这种情况下,您将引用“旧的、孤立的”会话,用户将再也看不到该会话
当线程死亡时,会话将随线程一起消失
因此,基本上,只要您有一个服务器实例,您没有集群,您的服务器没有交换会话,服务器没有重新启动(这是服务器可能保存和恢复会话的另一个点),并且会话没有超时,您就应该做得很好
是的,这些都是对您的技术的限制,它不会使技术出错,它只是限制了实现。如果您的应用程序和服务能够在这些约束条件下正常工作,那么您就是黄金,不用担心
是否允许我(在没有任何副作用的情况下)从servlet的doGet()方法中创建和启动新的Thread()
如果实施得当,这是很好的
将“Session”对象传递到线程中,以便稍后保存我的结果是否有效
public class Task extends Thread implements HttpSessionBindingListener {
public void run() {
while (true) {
someHeavyStuff();
if (isInterrupted()) return;
}
}
public void valueBound(HttpSessionBindingEvent event) {
start(); // Will instantly be started when doing session.setAttribute("task", new Task());
}
public void valueUnbound(HttpSessionBindingEvent event) {
interrupt(); // Will signal interrupt when session expires.
}
}