可以在会话或应用程序属性中存储Thread对象吗?

时间:2010-12-06 05:29:22

标签: java multithreading session

我不确定我是否在正确的轨道上,但我之前创建了一个Thread并将其存储在当前会话中,以便能够在其他Servlet中使用它。

当用户登录时,我需要一个会定期轮询Web服务服务器并检索更新的线程。当用户注销时,我想停止/暂停线程。

如果我在用户登录时创建了线程,如果我想在用户注销时暂停它,则需要对此线程的引用,然后在登录时再次启动它。

最好和正确的方法是什么?我是否应该从线程内部监视会话,如果用户已注销,请让线程返回以结束线程?

然后下次用户登录时,我可以创建一个新的后台线程?

***我需要线程在后台运行并轮询Web服务服务器以获取用于更新数据库的更新。它可能每5分钟轮询一次。

我不希望它一直在轮询,因此我试图根据用户登录的方式来控制它...当我们按顺序注销时,我将布尔运行设置为false停止线程。因为线程存储在应用程序上下文中,所以我可以在他们重新登录时将运行设置为true。

如何在后台运行并检查某些内容,例如您的互联网已启动?

我知道如何创建Thread,但我对如何终止它感到困惑,因为它需要在后台持续运行。

我是否使用线程来处理错误的事情?我应该使用其他东西吗?

再次感谢,希望这是一个更好的解释...

4 个答案:

答案 0 :(得分:3)

线程不可序列化,因此将其存储在会话中可能会有问题。

此外,停止或暂停线程可能会有问题,除非您对线程的Runnable进行编码以定期检查它是否已暂停/停止并采取相应措施。 (不推荐使用Thread.stop()Thread.pause()方法,您应该避免使用它们。它们可能会破坏JVM的稳定性。)

即使您解决了上述问题,也有许多资源管理问题需要解决。

  

我不确定自己是否走在正确的轨道上

总之,你不是,IMO。

您尚未解释为什么需要将线程与每个会话相关联,或者这些线程的用途。如果你这样做了,你会得到一些很好的建议,可以(很大程度上)避免上述问题。

<强>后续

  

我没有使用.stop和.pause。

好。

  

我使用布尔“runnable”来控制线程。

这是另一种选择。我更喜欢使用Thread.interrupt()机制,因为它允许您中断在I / O操作或wait(...)调用中被阻止的线程停止。

  

如果您正在轮询设备并需要访问返回的数据,该怎么办?什么是最好的方法?

可能最好的方法是在servlet初始化中创建一个线程或线程池,负责轮询设备。如果需要保存返回的数据,以便可以在后续HTTP请求中访问它,请将其放入(比方说)请求控制器可以访问的队列中。您可能需要一些基础结构来在一段时间后从队列中删除未收集的数据对象,等等。

答案 1 :(得分:3)

由于servlet本身将同时被多次实例化,因此创建更多线程并不明智。如果由于序列化问题而决定将应用程序在一天中跨多台计算机进行集群,则会遇到问题,因此您将自己锁定在开头。

此外,似乎您的问题可以使用客户端的AJAX池来完成。如果在没有刷新整个页面的情况下无法将它们显示给客户端,为什么要汇集Web服务服务器并检索更新?

想想这种情况:如果用户会话持续30分钟,并且用户没有注销,只是关闭浏览器窗口:你不会知道这发生了,你会在接下来的30分钟内合并那个webservice,这是浪费资源。

答案 2 :(得分:1)

你根本不应该在容器内创建Threads。这是为了什么?

如果它被其他servlet使用,它更可能属于应用程序属性,而不是会话属性,不是吗?或者你真的在为每个用户创建一个帖子吗?你真的不希望这样做。

答案 3 :(得分:0)

我可以看到,在后台线程中执行轮询服务器端可能有正当理由:例如,它可能需要比用户想要等待请求答案更长的时间。还有一个问题是,一些反歧视法(更确切地说是如何解释这些法律的指导原则)否定了JavaScript的使用,所以没有Ajax。

因此,如果没有其他办法,我建议在Servlet.init()中创建一个线程(或一个非常小的线程池)。此单个(或少量线程)应对所有活动用户进行轮询。在web.xml中,您可以定义会话侦听器,以便跟踪打开和关闭/过期的会话。

确保在Servlet.destroy()中发出线程应该存在的信号。

要定义会话实时循环侦听器,请在web.xml中添加:

<listener>
    <listener-class>
        com.example.SessionListener
    </listener-class>
</listener>

然后记住打开的会话,以便您可以在后台线程中迭代它们。

public class SessionListener implements HttpSessionListener {
    private Set<HttpSession> sessions = Collections.synchronizedCollections(
         new HashSet<HttpSession>());

    public void sessionCreated(HttpSessionEvent sessionEvent) {
        HttpSession session = sessionEvent.getSession();
        sessions.add(session;
    }

    public synchronized void sessionDestroyed(HttpSessionEvent sessionEvent) {
        HttpSession session = sessionEvent.getSession();
        sessions.remove(session);
    }
}