如何在Java中执行一个进程而不使程序冻结?我试过使用SwingWorker,但我还不太明白它是如何工作的。
有没有其他方法可以做到这一点?
提前感谢!
编辑:
谢谢你的回答。但是我有一个类有几个方法(好吧,它不止一个类,但是你明白我的意思);我如何使用SwingWorker与这些方法交互?
下面是其中一个类:
/**
*
* @author Simon
*/
public abstract class Command extends SwingWorker {
BufferedReader prReader = null;
ProcessBuilder process = null;
Process pr = null;
Date timeNow = new Date();
String osName = System.getProperty("os.name");
public void executeProcessNoReturn(String _process, String arg) throws IOException {
process = new ProcessBuilder(_process, arg);
pr = process.start();
}
public String executeProcessReturnLastLine(String _process, String arg) throws IOException {
process = new ProcessBuilder(_process, arg);
pr = process.start();
prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
String line;
while ((line = prReader.readLine()) != null) {
// Wait for input to end.
}
return line;
}
public StringBuilder executeProcessReturnAllOutput(String _process, String arg) throws IOException {
process = new ProcessBuilder(_process, arg);
pr = process.start();
prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
StringBuilder output = null;
String line;
while ((line = prReader.readLine()) != null) {
output.append(line);
}
return output;
}
public boolean isProcessRunning(String processName) throws IOException {
boolean value = false;
if (osName.equals("Linux") | osName.contains("Mac")) {
process = new ProcessBuilder("ps", "-e");
pr = process.start();
String line;
prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while ((line = prReader.readLine()) != null) {
if (line.contains(processName)) { value = true; break; }
}
} else {
String winDir = System.getenv("windir") + "/System32/tasklist.exe";
process = new ProcessBuilder(winDir);
pr = process.start();
String line;
prReader = new BufferedReader(new InputStreamReader(pr.getInputStream()));
while ((line = prReader.readLine()) != null) {
if (line.contains(processName)) { value = true; break; }
}
}
return value;
}
public String executeProcessReturnError(String processName, String arg) throws IOException {
process = new ProcessBuilder(processName, arg);
process.redirectError();
pr = process.start();
prReader = new BufferedReader(new InputStreamReader(pr.getErrorStream()));
String line;
String output = "";
while ((line = prReader.readLine()) != null) {
output += line + "\n";
}
return output;
}
}
字符串
3条答案
按热度按时间3bygqnnd1#
是的,你可以使用
SwingWorker
,这个想法是,一个需要花费大量时间的任务,你在一个单独的线程(后台线程)中运行,那么你就不会阻塞你的GUI,你的JFrame也不会冻结。基本上,作为一个例子,您创建自己的类,扩展
SwingWorker
覆盖doInBackground
。注意:你可以像普通类一样拥有字段。
范例:
字符串
您还阅读了有关
process(..)
publish(..)
和done()
的内容。在你的客户端代码里。
型
cyej8jka2#
您需要在单独的Thread中运行代码。在程序中运行和协调多个代码路径的关键字是“并发”:
http://docs.oracle.com/javase/tutorial/essential/concurrency/index.html的
多线程代码可能会变得非常棘手和难以调试,但Java提供了一些更高级别的抽象/概念,使使用多线程代码更不容易出错。
看看java.util.concurrent包中的这些概念。
由于多线程是您在使用AWT/Swing时必然会遇到的问题,因此有一些实用程序类/方法专门设计用于促进图形应用程序中的多线程。SwingWorker就是其中之一(另一个是例如SwingUtilities.invokeLater())。熟悉它们是个好主意,它们可以让你的生活更轻松,特别是对于简单的任务,这些任务的时间刚好足够长,否则就会冻结GUI。
scyqe7ek3#
如果你正在使用Swing,SwingWorker是一个很好的选择。
既然你提到你不明白它是如何工作的,我将给予一个简单的解释。
Swing事件处理代码是在event dispatch thread中完成的。因此,如果用户单击一个按钮(比如说更新按钮,它从服务器获取数据并在窗口中显示它们),则该按钮的触发器将在事件调度线程中调用。
如果你在同一个线程中获取数据,那么UI将冻结,因为它不能处理任何事件(你正在事件调度线程中运行代码)。
所以你应该在一个单独的线程中获取数据。但是在获取数据之后,你应该在事件调度线程中将其设置为视图。
Swing worker让这一切变得简单,你把繁重的任务放在
doInBackground
方法中(在我们的例子中是获取数据),然后从该方法返回繁重任务的输出(在我们的例子中是数据)。在swing worker的
done
方法中,您调用get
方法,该方法将给予您在doInBackground
方法中返回的数据。在那里,您使用新数据更新视图(例如将数据添加到TableModel)。当你现在在swing worker上调用
exectue
时,它将负责在一个单独的线程(不是事件调度线程)中运行doInBackground
,并将在事件调度线程中运行done
方法。因此,通过使用SwingWorker,您不必担心在EDT中处理UI事件的内部机制以及另一个线程中的耗时任务。