栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > 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号