栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

JavaFX GUI Updater实用程序类中的并发问题

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

JavaFX GUI Updater实用程序类中的并发问题

我自己可以解决此问题。

System.out
在各个地方添加几天后,结果发现问题出在
isUpdating
变量的并发问题上。当JavaFX线程位于
while
循环和中的
synchronized
块之间时,发生了问题
Updater.run
。我通过使
Updater.run
GUIUpdater.scheduleUpdate
方法在同一对象上同步来解决了这个问题。

我也将其

GUIUpdater
制成了仅静态对象,因为
Runnables
无论其他
GUIUpdater
实例如何,都有多个实例将放置在JavaFX事件队列中,从而阻塞了事件队列。总而言之,这是结果
GUIUpdater
类:

package be.pbeckers.javafxguiupdater;import java.util.concurrent.ConcurrentlinkedQueue;import javafx.application.Platform;import javafx.beans.property.Property;import javafx.beans.value.ChangeListener;import javafx.beans.value.Observablevalue;public abstract class GUIUpdater {    private static  ConcurrentlinkedQueue<PropertyUpdater<?>>   dirtyPropertyUpdaters   =   new ConcurrentlinkedQueue<>();    private static  Updater    updater      =   new Updater();    private static  boolean    isUpdating   =   false;        public static <T> void bind(Property<T> property, Observablevalue<T> observable) {        PropertyUpdater<T>  propertyUpdater = new PropertyUpdater<>(property, observable);        observable.addListener(propertyUpdater);    }        public static <T> void unbind(Property<T> property, Observablevalue<T> observable) {        PropertyUpdater<T>  tmpPropertyUpdater = new PropertyUpdater<>(property, observable);        observable.removeListener(tmpPropertyUpdater);    }        private static synchronized void scheduleUpdate(PropertyUpdater<?> updater) {        GUIUpdater.dirtyPropertyUpdaters.add(updater);        if (!GUIUpdater.isUpdating) { GUIUpdater.isUpdating = true; Platform.runLater(GUIUpdater.updater);        }    }        private static class PropertyUpdater<T> implements ChangeListener<T> {        private boolean  isDirty     =   false;        private Property<T>         property    =   null;        private Observablevalue<T>  observable  =   null;        public PropertyUpdater(Property<T> property, Observablevalue<T> observable) { this.property = property; this.observable = observable;        }        @Override                public synchronized void changed(Observablevalue<? extends T> observable, T oldValue, T newValue) { if (!this.isDirty) {     this.isDirty = true;     GUIUpdater.scheduleUpdate(this); }        }                public synchronized void update() { T value = this.observable.getValue(); this.property.setValue(value); this.isDirty = false;        }        @Override                public boolean equals(Object otherObj) { PropertyUpdater<?>  otherUpdater = (PropertyUpdater<?>) otherObj; if (otherObj == null) {     return false; } else {     // only compare addresses (comparing with equals also compares contents):     return (this.property == otherUpdater.property) && (this.observable == otherUpdater.observable); }        }    }        private static class Updater implements Runnable {        @Override        public void run() { synchronized (GUIUpdater.class) {     // Loop through the individual PropertyUpdaters, updating them one by one:     while(!GUIUpdater.dirtyPropertyUpdaters.isEmpty()) {         PropertyUpdater<?>  curUpdater = GUIUpdater.dirtyPropertyUpdaters.poll();         curUpdater.update();     }     // Mark as updated:     GUIUpdater.isUpdating = false;    }        }    }}

这是测试器类的稍有更新的版本(由于它完全不重要,因此我不对其进行详细介绍):

package be.pbeckers.javafxguiupdater.test;import be.pbeckers.javafxguiupdater.GUIUpdater;import javafx.application.Application;import javafx.beans.property.SimpleStringProperty;import javafx.concurrent.Task;import javafx.event.ActionEvent;import javafx.event.EventHandler;import javafx.scene.Scene;import javafx.scene.control.Button;import javafx.scene.control.Label;import javafx.scene.control.ProgressBar;import javafx.scene.layout.FlowPane;import javafx.stage.Stage;public class JavaFXTest extends Application {    private Label       lblCurFile      =   new Label();    private Label       lblErrors       =   new Label();    private Label       lblBytesParsed  =   new Label();    private ProgressBar prgProgress     =   new ProgressBar();    public static void main(String args[]) {        JavaFXTest.launch(args);    }    @Override    public void start(Stage primaryStage) throws Exception {        // Init window:        FlowPane    flowPane = new FlowPane();        primaryStage.setScene(new Scene(flowPane));        primaryStage.setTitle("JavaFXTest");        // Add a few Labels and a progressBar:        flowPane.getChildren().add(this.lblCurFile);        flowPane.getChildren().add(this.lblErrors);        flowPane.getChildren().add(this.lblBytesParsed);        flowPane.getChildren().add(this.prgProgress);        // Add button:        Button  btnStart = new Button("Start");        btnStart.setonAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) {     // Create task:     TestTask    testTask = new TestTask();     // Bind:     GUIUpdater.bind(JavaFXTest.this.lblCurFile.textProperty(), testTask.curFileProperty());     GUIUpdater.bind(JavaFXTest.this.lblErrors.textProperty(), testTask.errorsProperty());     GUIUpdater.bind(JavaFXTest.this.lblBytesParsed.textProperty(), testTask.bytesParsedProperty());     JavaFXTest.this.prgProgress.progressProperty().bind(testTask.progressProperty());   // No need to use GUIUpdater here, Task class provides the same functionality for progress.     // Start task:     Thread  tmpThread = new Thread(testTask);     tmpThread.start(); }        });        flowPane.getChildren().add(btnStart);        // Show:        primaryStage.show();    }        private class TestTask extends Task<Void> {        private SimpleStringProperty    curFile     =   new SimpleStringProperty();        private SimpleStringProperty    errors      =   new SimpleStringProperty();        private SimpleStringProperty    bytesParsed =   new SimpleStringProperty();        @Override        protected Void call() throws Exception { // Count: try {     int maxValue = 1000000;     long startTime = System.currentTimeMillis();     System.out.println("Starting...");     for(int i = 0; i < maxValue; i++) {         this.updateProgress(i, maxValue - 1);         // Simulate some progress variables:         this.curFile.set("File_" + i + ".txt");         if ((i % 1000) == 0) {  //this.errors.set("" + (i / 1000) + " Errors");         }         //this.bytesParsed.set("" + (i / 1024) + " KBytes");     }     long stopTime = System.currentTimeMillis();     System.out.println("Done in " + (stopTime - startTime) + " msec!"); } catch(Exception e) {     e.printStackTrace(); } // Unbind: GUIUpdater.unbind(JavaFXTest.this.lblCurFile.textProperty(), this.curFileProperty()); GUIUpdater.unbind(JavaFXTest.this.lblErrors.textProperty(), this.errorsProperty()); GUIUpdater.unbind(JavaFXTest.this.lblBytesParsed.textProperty(), this.bytesParsedProperty()); return null;        }        public SimpleStringProperty curFileProperty() { return this.curFile;        }        public SimpleStringProperty errorsProperty() { return this.errors;        }        public SimpleStringProperty bytesParsedProperty() { return this.bytesParsed;        }    }}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/495158.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号