我有一个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
}
}
}
答案 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
或代码的任何更改。最后一部分可能是最重要的部分,因为我自己没有编写程序,所以现在我不必阅读和理解程序。