我对使用线程非常不熟悉,所以我希望有人可以帮我找出最好的方法。
我的java应用程序中有一个JButton ...当你点击按钮时,我有一个Process Builder,它创建一个执行一些外部python代码的进程。 python代码生成一些文件,这可能需要一些时间。当python代码完成执行时,我需要将这些文件加载到我的Java应用程序中的applet中。
在目前的形式中,我在调用外部python文件的代码中有一个p.waitFor()...所以当你点击按钮时,按钮挂起(整个应用程序实际挂起)直到进程是完成。显然,我希望用户能够在此过程进行时与应用程序的其余部分进行交互,但是一旦完成,我希望我的应用程序知道它,以便它可以将文件加载到applet中
最好的方法是什么?
感谢您的帮助。
答案 0 :(得分:9)
您应该使用SwingWorker在后台线程上调用Python进程。这样,在长时间运行的任务运行时,您的UI将保持响应。
// Define Action.
Action action = new AbstractAction("Do It") {
public void actionPerformed(ActionEvent e) {
runBackgroundTask();
}
}
// Install Action into JButton.
JButton btn = new JButton(action);
private void runBackgroundTask() {
new SwingWorker<Void, Void>() {
{
// Disable action until task is complete to prevent concurrent tasks.
action.setEnabled(false);
}
// Called on the Swing thread when background task completes.
protected void done() {
action.setEnabled(true);
try {
// No result but calling get() will propagate any exceptions onto Swing thread.
get();
} catch(Exception ex) {
// Handle exception
}
}
// Called on background thread
protected Void doInBackground() throws Exception {
// Add ProcessBuilder code here!
return null; // No result so simply return null.
}
}.execute();
}
答案 1 :(得分:0)
您真的想要创建一个新线程来监控您的新流程。正如您所发现的那样,在UI和监视子进程时只使用一个线程将使子进程运行时UI似乎挂起。
这是一些示例代码,假设存在log4j记录器,我认为这将说明一种可能的方法......
Runtime runtime = Runtime.getRuntime();
String[] command = { "myShellCommand", "firstArgument" };
try {
boolean done = false;
int exitValue = 0;
Process proc = runtime.exec(command);
while (!done) {
try {
exitValue = proc.exitValue();
done = true;
} catch (IllegalThreadStateException e) {
// This exception will be thrown only if the process is still running
// because exitValue() will not be a valid method call yet...
logger.info("Process is still running...")
}
}
if (exitValue != 0) {
// Child process exited with non-zero exit code - do something about failure.
logger.info("Deletion failure - exit code " + exitValue);
}
} catch (IOException e) {
// An exception thrown by runtime.exec() which would mean myShellCommand was not
// found in the path or something like that...
logger.info("Deletion failure - error: " + e.getMessage());
}
// If no errors were caught above, the child is now finished with a zero exit code
// Move on happily