我正在尝试在执行cmd命令时获得响应式JavaFX图形界面。
我正在执行的命令如下。
youtube-dl.exe --audio-format mp3 --extract-audio https://www.youtube.com/watch?v=l2vy6pJSo9c
如您所见,这是一个YouTube下载器,可将YouTube链接转换为mp3文件。 我希望在第二个线程中执行,而不是在主 FX 线程中执行。
我已经通过在类StartDownloadingThread
中实现接口Callable
来解决这个问题。
@Override
public Process call() throws Exception {
Process p = null;
p = ExecuteCommand(localCPara1, localCPara2, localDirectory).start();
try {
Thread.sleep(30);
}catch (InterruptedException e){}
return p;
}
该方法ExecuteCommand
只返回一个ProcessBuilder
对象。
我尝试使用Thread.sleep
使程序返回到主线程,从而使应用程序响应。不幸的是,该程序仍然冻结。
这就是调用方法调用的方式。
ExecutorService pool = Executors.newFixedThreadPool(2);
StartDownloadingThread callable = new StartDownloadingThread(parameter1, parameter2, directory);
Future future = pool.submit(callable);
Process p = (Process) future.get();
p.waitFor();
如何使用界面Callable
使我的 GUI 响应?
使用执行器运行任务只是为了使用提交任务时返回的Future
的get
方法实际上并没有释放原始线程以继续执行其他任务。后来你甚至在原始线程上使用waitFor
方法,这可能比你在Callable
中所做的任何事情都要花费更多的时间。
为此,Task
类可能更适合,因为它允许您使用事件处理程序处理应用程序线程上的成功/失败。
此外,请确保在完成提交任务后关闭ExecutorService
。
Task<Void> task = new Task<Void>() {
@Override
protected Void call() throws Exception {
Process p = null;
p = ExecuteCommand(localCPara1, localCPara2, localDirectory).start();
// why are you even doing this?
try {
Thread.sleep(30);
}catch (InterruptedException e){}
// do the rest of the long running things
p.waitFor();
return null;
}
};
task.setOnSucceeded(event -> {
// modify ui to show success
});
task.setOnFailed(event -> {
// modify ui to show failure
});
ExecutorService pool = Executors.newFixedThreadPool(2);
pool.submit(task);
// add more tasks...
// shutdown the pool not keep the jvm alive because of the pool
pool.shutdown();