Java 异步处理=跨越线程=有效?

Java 异步处理=跨越线程=有效?,java,servlets,concurrency,Java,Servlets,Concurrency,是否允许我(没有任何副作用)从servlet的doGet()方法中创建并启动new Thread()?还是这会泄露资源 将“Session”对象传递到线程中,以便稍后在会话中保存异步处理的结果(我将正确同步)是否有效?或者在“独立线程”中使用会话时会泄漏资源 =>如果会话同时被webcontainer终止,因为它有timedout,我将从我的线程访问它,会发生什么?或者,这是否也会导致副作用,即将会话存储在线程中会阻止webcontainer终止会话(因此最终会泄漏资源,因为会话未被清除) (我

是否允许我(没有任何副作用)从servlet的
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.
    }

}