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