4

我有一个 Java 应用程序,它创建一个新线程来做一些工作。我可以毫无问题地启动新线程。

当“主”程序终止时,我希望我创建的线程继续运行 - 它确实......

但问题是,当我从 Eclipse 或 Windows 下的 Ant 运行主应用程序时,除非后台进程被杀死,否则控制不会返回。

如果我在ant中分叉主java进程,我希望控制权在主线程完成其工作后返回给ant......但事实上,ant继续等待,直到主进程和创建的线程都终止.

如何在后台启动线程,以便在“主”应用程序完成时将控制权返回给 ant?(顺便说一句,当我在 Linux 下运行相同的应用程序时,我可以毫无问题地做到这一点)。

4

6 回答 6

4

您最好的选择是为此启动一个完全独立的程序,该程序独立于启动程序。您可以使用或来做到这Runtime#exec()一点。ProcessBuilderDesktop#open()

于 2010-04-14T23:12:49.030 回答
2

您可能想要创建一个守护线程:thread.setDaemon (true)。

于 2010-04-14T23:05:16.593 回答
1

如果我正确理解了这个问题,那么似乎程序的行为是正确的......main线程完成并退出,而“ background”线程继续运行。在所有非守护线程终止之前,JVM 不会退出。如果您希望JVM进程在main线程终止时终止,您需要按照罗马指示并调用Thread.setDaemon(boolean).

但是,如果问题是main线程正确终止,但background从未终止,即使它已经完成了您给它的任务,那么可能background是死锁了。

最好的第一步 IMO 是在进程上运行VisualVM以转储堆栈并使用其线程调试工具来找出background正在做什么以及它挂起的原因。(如果在 *nix 上,您也可以通过发送堆栈来导致 JVM 转储堆栈kill -QUIT <pid>......在 Windows 上有类似的东西Break,但我不记得具体细节。)Java 6 中的堆栈转储非常复杂,并且将指示每个线程锁定的对象可能出现死锁。

VisualVM使用起来很有趣,所以如果您从未使用过它,请尝试一下。

于 2010-04-15T00:05:02.637 回答
0

听起来您需要“主”线程和“后台”线程成为单独的进程。fork 运行“主”线程的第一个进程。反过来,该进程派生出第二个运行“后台”线程的进程。在 Windows 上,您可能必须Runtime.exec()使用(通过 Java 的 API)启动后台进程start /b

我不明白这是如何在 Linux 下工作的。Process创建者要么正在运行,Runtime.exec()要么没有。当 Java 程序等待 aProcess完成时,它并不关心子进程中是否有一个线程或多个线程在运行。如果您可以更清楚地描述它如何在 Linux 下工作,它可能会有所帮助。

于 2010-04-14T23:27:58.733 回答
0

在一切完成之前,控制权不会从 JVM 返回。这意味着所有线程都必须返回,所有窗口都必须被销毁()——并且 main 必须退出。

或者你调用 System.exit()。

如果它确实在 Linux 上运行,我很确定你会发现你的后台线程也终止了——否则这是非常糟糕的。

于 2010-04-14T23:59:12.930 回答
0

我想通了。事实证明,在 Windows 中,从同一命令窗口启动的进程将等待子进程完成。

您可以在 Eclipse 中对此进行测试:制作程序并执行应用程序(例如 Notepad.exe)。您会发现 java 程序终止了,但红色按钮仍然处于活动状态。在您关闭应用程序(例如 notepad.exe)之前,控制权不会返回到 eclipse。这显然是因为您的 java 程序和 execed 程序使用相同的命令窗口。同样的事情也发生在 ANT 中。

在 linux 中,进程不会像在 windows 中那样继承命令窗口,因此当您的进程完成时,控制权会返回给 eclipse。

在这两种情况下,生成的进程都会保持活动状态,直到它被终止。

于 2010-04-16T23:24:36.397 回答