Multithreading 在VBox JavaFX中用ProgressIndicator替换TableView

Multithreading 在VBox JavaFX中用ProgressIndicator替换TableView,multithreading,javafx,tableview,progress-indicator,Multithreading,Javafx,Tableview,Progress Indicator,我有一个与一些数据相关联的TableView,一旦我点击run按钮,我就会对这些数据执行一些处理。每一行数据都在一个单独的线程中处理,当这些线程运行时,我需要一个ProgressInductor来替换其vbox中的表 在所附代码中: 若我停在哪里,若停在这里,那个么这个表就会被pi替换。 如果我继续等待线程加入-无需替换。 我错过了什么 runButton.setOnAction( new EventHandler<ActionEvent>()

我有一个与一些数据相关联的TableView,一旦我点击run按钮,我就会对这些数据执行一些处理。每一行数据都在一个单独的线程中处理,当这些线程运行时,我需要一个ProgressInductor来替换其vbox中的表

在所附代码中:

若我停在哪里,若停在这里,那个么这个表就会被pi替换。 如果我继续等待线程加入-无需替换。 我错过了什么

    runButton.setOnAction(
                new EventHandler<ActionEvent>() {
                    @Override
                    public void handle(final ActionEvent e) {
                        List<Thread> threadList = new ArrayList<Thread>();

                        int threadCounter = 0;
                        final ProgressIndicator pi = new ProgressIndicator(threadCounter);

                        vbox.getChildren().clear();
                        vbox.getChildren().addAll(pi);
                        for (ProductInTable product : data) {
                            Thread thread = new Thread(new Runnable() {
                                @Override
                                public void run() {
                                    try
                                    {
                                        product.calculate();
                                    } catch (IOException ioe) {
                                        ioe.printStackTrace();
                                    }
                                }
                            });
                            threadList.add(thread);
                            thread.start();
                        }

                        int x = threadList.size();

                        /** WORKS IF STOP HERE **/

                        // wait for all threads to end
                        for (Thread t : threadList) {
                            try {
                                t.join();
                                threadCounter++;
                                pi.setProgress(threadCounter / x);
                            } catch (InterruptedException interE) {
                                interE.printStackTrace();
                            }
                        }

                        /** DOESNT WORKS IF STOP HERE **/
在线程完成之前,Thread.join会阻止执行。由于您是在FX应用程序线程上调用此函数,因此将阻止该线程,直到所有工作线程完成。这意味着在这些线程完成之前,UI无法更新

更好的方法可能是用一个任务表示每个计算,并使用setOnSucceeded将完成任务的计数器更新回FX应用程序线程。比如:

runButton.setOnAction(
            new EventHandler<ActionEvent>() {
                @Override
                public void handle(final ActionEvent e) {

                    final ProgressIndicator pi = new ProgressIndicator(threadCounter);

                    vbox.getChildren().clear();
                    vbox.getChildren().addAll(pi);

                    final int numTasks = data.size();

                    // only access from FX Application thread:
                    final IntegerProperty completedTaskCount = new SimpleIntegerProperty(0);

                    pi.progressProperty().bind(completedTaskCount.divide(1.0*numTasks));

                    completedTaskCount.addListener(new ChangeListener<Number>() {
                        @Override
                        public void changed(ObservableValue<? extends Number> obs, Number oldValue, Number newValue) { 
                            if (newValue.intValue() >= numTasks) {
                                // hide progress indicator and show table..
                            }
                        }
                    });

                    for (final ProductInTable product : data) {
                        Task<Void> task = new Task<Void>() {
                            @Override
                            public Void call() {
                                try
                                {
                                    product.calculate();
                                } catch (IOException ioe) {
                                    ioe.printStackTrace();
                                }
                                return null ;
                            }
                        });
                        task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
                            @Override
                            public void handle(WorkerStateEvent event) {
                                completedTaskCount.set(completedTaskCount.get()+1);
                            }
                        });
                        new Thread(task).start();
                    }

                }
});
然后更换

new Thread(task).start();


这取决于平台,对于这个问题我没有一个好的答案。我想我总是试图保持与系统上处理器数量相同的数量级;但我不确定这是否是一项好政策。如果您有疑问,我建议使用ExecutorService来管理计划。
new Thread(task).start();
exec.submit(task);