Java 当使用while循环检查任务何时完成时,GUI被阻止

Java 当使用while循环检查任务何时完成时,GUI被阻止,java,javafx,task,Java,Javafx,Task,我这里有一段代码,基本上这是要做的,当用户按下“Listen”按钮时,这段代码就运行了 在for循环中,我们得到一个名字(例如“John”),通过bash命令播放“John”的录音;等待名称完成播放(while循环),然后继续获取下一个名称并播放该名称(以此类推)。然而,我认为while循环阻塞了javafx中的GUI,有什么更好的解决方案 我想做的另一件事是,当线程启动时,我想检查是否再次按下“Listen”按钮(如果是,我想停止线程/任务) 我该怎么做 for (String s : _us

我这里有一段代码,基本上这是要做的,当用户按下“Listen”按钮时,这段代码就运行了

在for循环中,我们得到一个名字(例如“John”),通过bash命令播放“John”的录音;等待名称完成播放(while循环),然后继续获取下一个名称并播放该名称(以此类推)。然而,我认为while循环阻塞了javafx中的GUI,有什么更好的解决方案

我想做的另一件事是,当线程启动时,我想检查是否再次按下“Listen”按钮(如果是,我想停止线程/任务)

我该怎么做

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);
}