Java线程start()在servlet中没有join()或interrupt()

时间:2009-09-01 13:32:38

标签: java multithreading servlets

我有一个servlet过滤器,它携带一些逻辑并在它的主页面提供请求之前产生输出。我有一个新的需要发送输出几秒钟,比它生成时(延迟~10s)。由于先前做出的某些糟糕的设计选择,我无法移动过滤器的位置只是为了在之后发送输出。

我选择产生一个线程并延迟传输消息。我目前没有采取任何明确的步骤来停止执行此线程。我不确定是否所有东西都得到了适当的清理。我应该使用join()或interrupt()或任何其他Thread方法在此之后安全清理吗?

所以在主servlet代码中我有这样的东西......

Thread t = new Thread(new MessageSender(message, 10000));
t.start();
//Carry on.. la la la

虽然这个类中还有其他字段,但我只是删除了很多非必要的东西,比如建立数据库连接等,以明确这一点。

private static class MessageSender implements Runnable {
    String message;
    int delay;

    public MessageSender(String message, int delay) {
        this.message = message;
        this.delay = delay;
    }

    public void run() {
        try {
            Thread.sleep(delay);
            System.out.println(new java.util.Date() + ": hello world");                
        } catch (InterruptedException e) {
            // Do blah
        } catch (Exception e) {
            // Do blah blah
        } finally {
            // Close connections and stuff
        }
    }
}

4 个答案:

答案 0 :(得分:4)

您的代码应该没问题,VM一旦完成就会清理它。

但是,我建议不要使用这样的原始线程,而是使用java.util.concurrent.ScheduledExecutorService,使用java.util.concurrent.Executors创建。这是一个更好的抽象,可以更好地控制你的线程分配。

答案 1 :(得分:1)

是的,一切都会得到妥善清理。线程在完成run()方法后死亡,因为你没有更多对该线程对象的引用 - 它将被正确地垃圾收集。

请确保“Thread t”对象不会被任何引用。为了确保这一点,你可以使用: (新线程(...))。start();

答案 2 :(得分:1)

servlet规范明确指出(“线程安全”一节)请求和响应对象不保证是线程安全的,如果这些对象被移交给其他线程,那么应用程序负责确保这些对象是同步的,只能在servlet的服务方法范围内访问它们。换句话说,你必须.join()那些线程。

答案 3 :(得分:0)

我必须自己回答同样的问题:)

我可以承认线程在完成后确实已经清理完了。如果您不完全确定生成的线程是否已经死亡,您应该能够监视进程并查看它当前运行的线程数。如果这个数字不断增长,那么就会有一些失控。

在Unix系统上,你可以使用ps命令,但我生锈了,所以我问google而不是阅读man-page。 谷歌的第一次点击之一是This script that lists threads for each process。输出看起来像这样

PID TID CLS RTPRIO  STAT    COMMAND WCHAN
....
16035   16047   TS  -   S   (java)  
16035   16050   TS  -   S   (java)  
16035   16054   TS  -   S   (java)  
16035   16057   TS  -   S   (java)  
16035   16058   TS  -   S   (java)  
16035   16059   TS  -   S   (java)  
16035   16060   TS  -   S   (java)  
....

我只是grep我想要观察的进程的进程id(pid)的输出并计算行数,每行对应一个线程。像这样:

morten@squeeze: ~$ sh /tmp/list_threads.sh | grep 16035 | wc -l
20

因此我正在观看的节目(PID 16035)有20个线程正在运行。

这不需要了解jconsole或代码的任何更改。最后一部分可能是最重要的部分,因为我自己没有编写程序,所以现在我不必阅读和理解程序。