我们如何从servlet启动线程?

时间:2014-03-05 04:24:09

标签: java servlets

从servlet启动线程的推荐方法是什么?

示例:一位用户将新的聊天消息发布到游戏室。我想向连接到房间的所有其他玩家发送推送通知,但不必同步发生。类似的东西:

public MyChatServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, 
                          HttpServletResponse response) 
    {
        // Update the database with the new chat message.
        final String msg = ...;
        putMsgInDatabaseForGameroom(msg);

        // Now spawn a thread which will deal with communicating
        // with apple's apns service, this can be done async.
        new Thread() {
            public void run() {
                talkToApple(msg);
                someOtherUnimportantStuff(msg);
            }
        }.start();

        // We can send a reply back to the caller now.
        // ...
    }
}

我正在使用Jetty,但我不知道Web容器在这种情况下是否真的很重要。

由于

4 个答案:

答案 0 :(得分:1)

  

从servlet启动线程的推荐方法是什么?

在servlet中编写线程程序时应该非常小心。 因为它可能导致错误(如内存泄漏或缺少同步)可能导致很难重现的错误, 或者关闭整个服务器。

您可以使用start()方法启动该线程。

据我所知,我建议使用startAsync(servlet 3.0)。 我为您Click提供了一些有用的链接。

  

但我不知道在这种情况下Web容器是否真的很重要。

是的,它很重要。大多数网络服务器(Java和其他方面,包括JBoss)遵循“每个请求一个线程”模型,即每个HTTP请求完全由一个线程完全处理。 这个线程通常会花大部分时间等待DB请求之类的事情。 Web容器将根据需要创建新线程。

希望它会对你有所帮助。

答案 1 :(得分:0)

一般来说就是这样。您可以在servlet Web应用程序中的任何位置启动任何线程。

但特别是,您应该保护您的JVM免于在任何HTTP请求上启动太多线程。有人可能会请求很多(或非常非常)并且可能在某些时候你的JVM将停止内存不足或类似的东西。

更好的选择是使用java.util.concurrent包中的其中一个队列。

答案 2 :(得分:0)

一种选择是使用ExecutorService和它的实现(如ThreadPoolExecutor )来重用池化线程,从而减少创建开销。

您也可以使用JMS排队等待稍后执行的任务。

答案 3 :(得分:0)

我会使用ThreadPoolExecutor并将任务提交给它。执行程序可以配置固定/不同数量的线程,以及可以绑定或不绑定的工作队列。

优点:

  • 线程总数(以及队列大小)可以限制,因此您可以很好地控制资源消耗。
  • 汇集线程,消除了每个请求启动线程的开销
  • 您可以选择任务拒绝策略(在池满负荷时发生)
  • 您可以轻松监控池上的负载
  • 执行程序机制支持跟踪异步操作的便捷方式(使用Future