Java 当使用while循环检查任务何时完成时,GUI被阻止
我这里有一段代码,基本上这是要做的,当用户按下“Listen”按钮时,这段代码就运行了 在for循环中,我们得到一个名字(例如“John”),通过bash命令播放“John”的录音;等待名称完成播放(while循环),然后继续获取下一个名称并播放该名称(以此类推)。然而,我认为while循环阻塞了javafx中的GUI,有什么更好的解决方案 我想做的另一件事是,当线程启动时,我想检查是否再次按下“Listen”按钮(如果是,我想停止线程/任务) 我该怎么做Java 当使用while循环检查任务何时完成时,GUI被阻止,java,javafx,task,Java,Javafx,Task,我这里有一段代码,基本上这是要做的,当用户按下“Listen”按钮时,这段代码就运行了 在for循环中,我们得到一个名字(例如“John”),通过bash命令播放“John”的录音;等待名称完成播放(while循环),然后继续获取下一个名称并播放该名称(以此类推)。然而,我认为while循环阻塞了javafx中的GUI,有什么更好的解决方案 我想做的另一件事是,当线程启动时,我想检查是否再次按下“Listen”按钮(如果是,我想停止线程/任务) 我该怎么做 for (String s : _us
for (String s : _userDatabase.getSelectedNames()) {
Task<Integer> task = new Task<Integer>() {
try {
Process pb = new ProcessBuilder("bash", "-c", //SomeCommand).start();
return pb.waitFor();
} catch (IOException e) {
e.printStackTrace();
return 1;
}
};
Thread playAudio = new Thread(task);
playAudio.setDaemon(true);
playAudio.start();
while(!task.isDone()){
}
}
for(字符串s:\u userDatabase.getSelectedNames()){
任务=新任务(){
试一试{
Process pb=new ProcessBuilder(“bash”、“-c”、//SomeCommand).start();
返回pb.waitFor();
}捕获(IOE异常){
e、 printStackTrace();
返回1;
}
};
线程播放音频=新线程(任务);
playAudio.setDaemon(true);
playAudio.start();
而(!task.isDone()){
}
}
没有理由忙着等待任务完成。任务
提供了许多方法,可以在任务达到某个状态时注册回调。其中一种机制是使用EventHandler
s和各种属性(例如onSucceeded
,onFailed
,等等)。您还可以收听任何适当的工作者
属性(例如状态
,值
,异常
,等等)
注意:如果在ScheduledService
中重写这些方法,请确保根据需要调用超级实现。有关更多信息,请参阅Javadoc
只有在上一个任务完成后,才可以通过几种方法启动下一个任务。一种是使用单个线程启动所有任务
s并将它们排队
ExecutorService executor = Executors.newSingleThreadExecutor();
for (String s : _userDatabase.getSelectedNames()) {
Task<Integer> task = ...;
// add callbacks to task if necessary
executor.execute(task);
}
executor.shutdown();
第三种选择是在单个任务中完成所有工作。基本上,将for
循环放入call()
方法中。没有理由忙着等待任务完成。任务
提供了许多方法,可以在任务达到某个状态时注册回调。其中一种机制是使用EventHandler
s和各种属性(例如onSucceeded
,onFailed
,等等)。您还可以收听任何适当的工作者
属性(例如状态
,值
,异常
,等等)
注意:如果在ScheduledService
中重写这些方法,请确保根据需要调用超级实现。有关更多信息,请参阅Javadoc
只有在上一个任务完成后,才可以通过几种方法启动下一个任务。一种是使用单个线程启动所有任务
s并将它们排队
ExecutorService executor = Executors.newSingleThreadExecutor();
for (String s : _userDatabase.getSelectedNames()) {
Task<Integer> task = ...;
// add callbacks to task if necessary
executor.execute(task);
}
executor.shutdown();
第三种选择是在单个任务中完成所有工作。基本上,将for
循环放在call()
方法中。我使用for循环的困难在于,如何确保for循环的下一次迭代仅在任务完成时运行?@bigfocalchord更新了答案。第一种方法很好,我使用了它。但是问题是,如果按下“停止”按钮,我如何在任务内部不断检查。因为如果按下那个按钮,我想停止任务immediatly@bigfocalchord单击按钮时,可以调用Task.cancel()
或调用ExecutorService.shutdownNow()
。后者也将停止任何剩余的任务的执行。然后在任务中
使其具有中断/取消意识。请注意,Process.waitFor()
是可中断的,在适当的时候会抛出一个InterruptedException
。当我按下按钮时,我调用:ExecutorService.Shutdownow(),然而,这给了我一个java.util.concurrent.RejectedExecutionException::Controllers.PracticeModelController$1@692d382d已从java.util.concurrent中拒绝。ThreadPoolExecutor@1186fb14My使用for循环时出现问题,如何确保for循环的下一次迭代仅在任务完成时运行?@bigfocalchord更新了答案。第一种方法很好,我使用了它。但是问题是,如果按下“停止”按钮,我如何在任务内部不断检查。因为如果按下那个按钮,我想停止任务immediatly@bigfocalchord单击按钮时,可以调用Task.cancel()
或调用ExecutorService.shutdownNow()
。后者也将停止任何剩余的任务的执行。然后在任务中
使其具有中断/取消意识。请注意,Process.waitFor()
是可中断的,在适当的时候会抛出一个InterruptedException
。当我按下按钮时,我调用:ExecutorService.Shutdownow(),然而,这给了我一个java.util.concurrent.RejectedExecutionException::Controllers.PracticeModelController$1@692d382d已从java.util.concurrent中拒绝。ThreadPoolExecutor@1186fb14
ExecutorService executor = Executors.newSingleThreadExecutor();
for (String s : _userDatabase.getSelectedNames()) {
Task<Integer> task = ...;
// add callbacks to task if necessary
executor.execute(task);
}
executor.shutdown();
private void execute(final List<String> names, final Executor executor,
final Consumer<Task<Integer>> onNewTask) {
Objects.requireNonNull(names);
Objects.requireNonNull(executor);
Objects.requireNonNull(onNewTask);
if (names.isEmpty()) {
return;
}
final Iterator<String> iterator = names.iterator();
class TaskImpl extends Task<Integer> {
private final String name;
private TaskImpl(String name) {
this.name = name;
}
@Override
protected Integer call() throws Exception {
// background work...
}
@Override protected void succeeded() { complete(); }
@Override protected void failed() { complete(); }
// @Override protected void cancelled() { complete(); }
private void complete() {
if (iterator.hasNext()) {
TaskImpl task = new TaskImpl(iterator.next());
onNewTask.accept(task);
executor.execute(task);
}
}
}
// launch first task
TaskImpl firstTask = new TaskImpl(iterator.next());
onNewTask.accept(firstTask);
executor.execute(firstTask);
}