JavaFX : Use a Thread more than once

2019-04-05 05:10发布

I'm new with JavaFX and I've a little problem with a thread: I can execute it twice and I can't find why.

Here is a sum-upt of my code:

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

When I click a first time the button who start my thread, my task run without any problem (my console display "GO !" and "SUCCEEDED").

But if I click a second time, nothing append. Am I doing something wrong ? Can't we use a thread more than once ?

3条回答
混吃等死
2楼-- · 2019-04-05 05:49

From the Thread.start() documentation : No

It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.

From the Concurrency in JavaFX tutorial :

The Task class defines a one-time object that cannot be reused. If you need a reusable Worker object, use the Service class.

So, you have to consider the Service class rather than Task.


Edit: this should work for you:

Service service = new Service<>(task);

//Updated use this to create a new Service object instead
    Service service = new Service() {
    @Override
    protected Task createTask() {
        return new Task() {
            @Override
            protected Void call() throws Exception {
                //Your codes here
                return null;
            }
        };
    }
};

@FXML protected void launch(ActionEvent event){
     if (!service.isRunning()) {
        service.reset();
        service.start();
    }
}
查看更多
对你真心纯属浪费
3楼-- · 2019-04-05 05:59

Do it with a wraper class

            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);
                            }
                }
            }
查看更多
我欲成王,谁敢阻挡
4楼-- · 2019-04-05 06:06

With a button can fire new tasks

                    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...");
                        }
                    });
查看更多
登录 后发表回答