[英]JavaFX8 Background Thread still interferes with GUI
我想編寫一個JavaFX GUI,該加載和解析一個較大的文件(22M)大約需要30秒。 但是,當我在Task中開始解析時,其余的GUI卻反應遲鈍。 但是,它並不是完全沒有響應,但仍會不時地掛起幾秒鍾。 為了證明這一點,我編寫了一個小應用程序,在進度條中顯示了解析的進度,並並行執行另一個任務,該任務僅每秒更新一次標簽。 現在,第二個任務不應被第一個任務阻止,因此我可能做錯了。 這是代碼:
每秒滴答滴答的任務:
class TimeTask extends Task<Void> {
@Override
protected Void call() throws Exception {
while (true) {
updateMessage(Instant.now().toString());
Thread.sleep(1000);
}
}
}
用於解析日志文件的替換:從解析器以100ms的步長調用update方法。
public class ParseLogfileTask extends Task<Void> {
private LinkedList<Integer> numbers = new LinkedList<Integer>();
private Random random = new Random();
@Override
protected Void call() {
Instant startInstant = Instant.now();
while (Duration.between(startInstant, Instant.now()).getSeconds() < 25) {
for (int i = 0; i < 10000000; i++) {
numbers.add((Integer) random.nextInt());
}
Collections.shuffle(numbers);
Collections.sort(numbers);
numbers.clear();
updateParseProgress(
(int) Duration.between(startInstant, Instant.now())
.toMillis(), 25000);
}
return null;
}
public void updateParseProgress(int currentIndex, int maxIndex) {
updateProgress(currentIndex, maxIndex);
}
}
應用程序的啟動方法:
@Override
public void start(Stage primaryStage) {
try {
Group root = new Group();
Scene scene = new Scene(root, 400, 400);
VBox vbox = new VBox();
vbox.setAlignment(Pos.CENTER);
ProgressBar bar = new ProgressBar();
Label label = new Label("new");
vbox.getChildren().addAll(bar, label);
root.getChildren().add(vbox);
primaryStage.setScene(scene);
primaryStage.show();
Task<Void> timeTask = new TimeTask();
Task<Void> logFileTask = new ParseLogfileTask();
bar.progressProperty().bind(logFileTask.progressProperty());
label.textProperty().bind(timeTask.messageProperty());
Platform.runLater(() -> {
new Thread(timeTask).start();
new Thread(logFileTask).start();
});
}
catch (Exception e) {
e.printStackTrace();
}
}
編輯:我刪除了timeTask開始后5秒鍾的睡眠。 對於真正的問題,這不是必需的。 真正的問題是,只要logfileTask正在運行,timeTask不會每秒更新一次標簽。 僅每1-5秒更新一次。 一旦logfileTask完成,timeTask就會完全按照原樣更新標簽。 這可能與線程優先級有關嗎? logfileTask產生了很大的負擔...
編輯2:我無法通過使用其他方式來創建負載來重現該問題。 我只有ANTLR創建的解析器有這些問題,解析器創建了一個巨大的解析樹(許多對象)。 但是,由於解析器是在后台線程中啟動的,它如何干擾JavaFX Application線程?
編輯3:看起來確實是垃圾回收。 我將日志文件解析替換為生成大量數字,對其進行排序並再次將其丟棄,從而看到了與運行解析器時相同的差距(不是經常出現,但是影響更大)
您在ParseLogfileTask中調用的許多操作有很多方法。 就像一陣子(真)。 在返回null之前使用Thread.sleep。
@Override
protected Void call() {
Instant startInstant = Instant.now();
while (Duration.between(startInstant, Instant.now()).getSeconds() < 25) {
for (int i = 0; i < 100000; i++) {
numbers.add((Integer) random.nextInt());
}
Collections.shuffle(numbers);
Collections.sort(numbers);
numbers.clear();
updateParseProgress(
(int) Duration.between(startInstant, Instant.now())
.toMillis(), 25000);
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
}
}
return null;
}
所以對我有用。
此外,最好使用
ExecutorService service = Executors.newFixedThreadPool(2); service.execute(timeTask); service.execute(logFileTask);
用於調用您的線程。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.