JavaFX: использование потока более одного раза

Я новичок в JavaFX, и у меня небольшая проблема с потоком: я могу выполнить его дважды, и я не могу найти почему.

Вот сумма моего кода:

Task<Void> task = new Task<Void>() {
    @Override public Void call() throws ImageLoadedException, HomographyException, IOException {
        try{
            System.out.println("GO !");
            return null;
        }
        catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    @Override
    protected void succeeded() {
        super.succeeded();
        System.out.println("SUCCEEDED");
     }
};

@FXML protected void launch(ActionEvent event){
    new Thread(task).start();
}

Когда я впервые нажимаю кнопку, которая запускает мой поток, моя задача запускается без каких-либо проблем (мой консольный дисплей "GO!" и "SUCCEEDED" ).

Но если я нажму второй раз, ничего не добавлю. Я делаю что-то неправильно? Не можем ли мы использовать поток более одного раза?

Ответ 1

В документации Thread.start(): Нет

Невозможно запустить поток более одного раза. В частности, нить не может быть перезапущена после завершения выполнения.

Из Concurrency в JavaFX:

Класс Task определяет одноразовый объект, который нельзя использовать повторно. если ты нужен объект многократного использования, используйте класс службы.

Итак, вы должны рассмотреть класс Service, а не Task.


Изменить: это должно работать для вас:

Service<Void> service = new Service<>(task);

@FXML protected void launch(ActionEvent event){
     if (!service.isRunning()) {
        service.reset();
        service.start();
    }
}

Ответ 2

С помощью кнопки можно запускать новые задачи

                    Button btn = new Button();
                    btn.setText("New task");
                    btn.setOnAction(new EventHandler<ActionEvent>() {
                        @Override
                        public void handle(ActionEvent event) {
                            Executor ex=new Executor("Task"+count);
                            ex.start();
                            count++;
                            System.out.println("Task  Starting...");
                        }
                    });

Ответ 3

Сделайте это с помощью класса wraper

            import java.io.IOException;
            import javafx.concurrent.Task;

            public class Executor {
                private String name;
                private Task<Void> task;

                public Executor(final String name) {
                    this.name=name;
                    task = new Task<Void>() {
                        @Override
                        public Void call() throws IOException, InterruptedException {
                            try {
                                int i=0;
                                while(i<20){
                                    System.out.println(name);
                                    Thread.sleep(2000);
                                    i++;
                                }
                                return null;
                            } catch (IllegalThreadStateException e) {
                                System.out.println(e);
                            }
                            return null;
                        }

                        @Override
                        protected void succeeded() {
                            super.succeeded();
                            try {
                                System.out.println(name+"  finish");
                            } catch (Exception ex) {
                                System.out.println(ex);
                            }
                        }
                    };
                }

                public void start() {
                    try {
                                Thread th = new Thread(task);
                                th.start();
                            } catch (Exception ex) {
                                System.out.println(ex);
                            }
                }
            }