gpt4 book ai didi

JavaFX : Running parallel threads and update overall progress to a ProgressBar

转载 作者:行者123 更新时间:2023-11-30 02:00:21 28 4
gpt4 key购买 nike

我需要一些工作负载分配给线程,并并行启动它们,因为它们是独立的。我还想使用 JavaFx 在 ProgressBar 中显示总体进度。这意味着进度条显示到目前为止每个线程完成的总工作

为了简单起见,我们可以以这个 Counter 类为例

public class Counter implements Runnable {
private int from, to;

public Counter(int from, int to) {
this.from = from;
this.to = to;
}

@Override
public void run() {
for (int i = from; i < to ; i++) {
// Do some heavy operation
// report about progress to the parent
}

// exit thread with status of success or failure
}
}

此类采用 from、to 作为边界条件。

为了不阻塞 UI,我使用一个简单的 Task 类,如下所示

public class MyTask extends Task<Integer> {
int iter;

public MyTask(int iter) {
this.iter = iter;
}

@Override
protected Integer call() throws Exception {
// Simply divide work load to each thread
int workers = 8;
int limit = iter/workers;
int rem = iter % workers;

// Creates a executor
ExecutorService executorService = Executors.newFixedThreadPool(workers);
for (int i = 0; i < workers; i++) {
int start = limit * i;
int end = limit * (i + 1);
if (i == workers - 1) end += rem;

Counter counter = new Counter(start, end);
executorService.submit(counter); // Submit work to be done
}

executorService.shutdown(); // start the execution

// Get their progress, update overall progress to UI
// Stop after all threads finished
}
}

MyTask 中,我想更新 UI,如评论中所述,并整体完成。 (即每个线程完成的总计数)。

有什么方法可以做到这一点吗?聚合并行任务的进度并更新 UI 中的总体进度(我不计算已完成的线程数,而是我要向 MyTask 报告的每个线程的当前进度)。

最佳答案

根据并行运行的任务数量,您可以简单地将 Task 用于 Counter 逻辑,并将监听器的总体进度更新为 progress 这些任务的属性。

如果并行运行的任务太多,这可能会减慢 JavaFX 应用程序线程的速度,因为太多 Runnable 可能正在等待同时执行。

您可以通过使用 synchronized 语句自行根据进度差异实现更新。为了简单起见,以下代码从 javafx 应用程序线程启动更新,但可以将此逻辑移动到不同的线程而不会导致任何问题:

@Override
public void start(Stage primaryStage) {
ProgressBar progressBar = new ProgressBar();

int workers = 8;

ExecutorService executorService = Executors.newFixedThreadPool(workers);

final int taskCount = 12;
final int elementsPerTask = 50;
final int elementCount = elementsPerTask * taskCount;

ProgressReceiver progressReceiver = new ProgressReceiver() {

private boolean updating = false;
private int progress = 0;

@Override
public void acceptProgress(int oldValue, int newValue) {
synchronized(this) {
progress += newValue - oldValue;
if (!updating) {
updating = true;
Platform.runLater(() -> {
synchronized (this) {
updating = false;
progressBar.setProgress(((double) progress) / elementCount);
}
});
}
}
}

};
for (int i = 0; i < taskCount; i++) {
int start = elementsPerTask * i;
int end = elementsPerTask * (i + 1);

Counter counter = new Counter(start, end, progressReceiver);
executorService.submit(counter);
}

executorService.shutdown();

StackPane root = new StackPane(progressBar);

Scene scene = new Scene(root, 300, 300);

primaryStage.setScene(scene);
primaryStage.show();
}
public interface ProgressReceiver {
void acceptProgress(int oldValue, int newValue);
}
public class Counter implements Runnable {

private final ProgressReceiver progressReceiver;

private final int from, to;

public Counter(int from, int to, ProgressReceiver progressReceiver) {
this.from = from;
this.to = to;
this.progressReceiver = progressReceiver;
}

@Override
public void run() {
for (int i = from; i < to; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
}
int oldProgress = i - from;
progressReceiver.acceptProgress(oldProgress, oldProgress + 1);
}

// exit thread with status of success or failure
}
}

关于JavaFX : Running parallel threads and update overall progress to a ProgressBar,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53089402/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com