我编写了一个在服务器上运行并侦听某些端口的程序。由于大部分时间都没有任何关系,我设置了一个阻止程序停止的线程。
我的解决方案如下所示:
Thread mainThread = new Thread( new Runnable() {
@Override
public void run() {
// run program continuously
while ( true ) {
try {
// since we aren't doing anything, the thread can sleep
Thread.sleep( Long.MAX_VALUE );
}
catch ( InterruptedException e ) {
e.printStackTrace();
}
}
}
} );
mainThread.start();
我的问题是: 常量 Long.MAX_VALUE 会出现问题并导致错误吗?我想一直运行程序,所以在我看来,线程不需要做任何事情。迄今为止最简单的解决方案是将其置于(非常非常深)睡眠状态(毫秒值大致转换为146.235.600年)。
答案 0 :(得分:1)
只要有一个线程仍在运行或阻塞,多线程程序就会继续运行。不是因为原始线程退出而导致程序退出的情况。您的程序可能有一个等待连接到端口的线程,因此您不需要这样做。
答案 1 :(得分:0)
要直接回答这个问题,没有理由认为任何(正)时间的睡眠,包括Long.MAX_VALUE
,都会与你预期的不同。
至于你是否需要这样做,我会回应其他人的评论,从设计的角度来看,它可能不是最好的事情,并且最有可能做出更好的架构决策来避免这种软糖(例如如果你想要停止应用程序退出,那么让守护程序线程成为非守护进程。)但是,从技术上讲,是的 - 线程应该在几个世纪的最佳时间内进入睡眠状态。
答案 2 :(得分:0)
当Java虚拟机启动时,通常会有一个非守护程序线程(通常调用某个指定类的名为main的方法)。 Java虚拟机继续执行线程,直到发生以下任一情况:
已调用类Runtime的exit方法,安全管理器已允许退出操作。
所有非守护程序线程的线程都已死亡,无论是通过从run方法的调用返回还是抛出一个超出run方法传播的异常。
似乎您的应用程序将始终在没有某种形式的“保持活动”机制的情况下关闭,因为在您使用的框架中启动的线程都是daemon
个线程。
像你所做的那样,防止这种情况的简单方法是让一个非守护程序线程保持活动并运行。
您发布的代码,正如其他人所指出的那样,似乎有点“简单”,但从技术上讲,它没有任何问题。
首先,我可以建议将其简化为一小部分 - 删除对new Runnable()
的多余使用,并删除对e.printStackTrace()
的调用。
关于使用Long.MAX_VALUE
作为Thread.sleep的参数,正如其他人所评论的那样,这完全没问题。然而,通过某种常规的“健康检查”会更好,这样如果您使用的框架突然崩溃或退出,那么您的主线程也将如此。
这是我的建议:
Thread mainThread = new Thread() {
@Override
public void run() {
// check if application is healthy at regular intervals
while ( myApplication.isHealthy() ) {
try {
Thread.sleep( 30 );
} catch ( InterruptedException e ) {
// ignore this, or log at DEBUG level
}
}
}
};
mainThread.start();
关于改进机制或寻找其他方法,我简要地研究了以下备选方案,但都没有结果。
BlockingQueue - 其他高级并发对象也可以无限期地“阻止”,但它们通常也会抛出InterruptedException
,并且肯定不如Thread.sleep
ShutdownHook - 如果所有剩余的线程都是守护进程(如果是这样),则关闭钩子不会停止jvm停止
创建另一个线程非守护进程 - 虽然您可以轻松找到其他正在运行的线程,但一旦线程启动就无法在线程上调用setDaemon(false)
。
总之,根据具体情况,您正在做的事情很好 - 如果可以,您可以考虑定期检查您的框架是否健康。