Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Multithreading JavaFX并发:多线程修改sinle StringProperty_Multithreading_Properties_Concurrency_Javafx - Fatal编程技术网

Multithreading JavaFX并发:多线程修改sinle StringProperty

Multithreading JavaFX并发:多线程修改sinle StringProperty,multithreading,properties,concurrency,javafx,Multithreading,Properties,Concurrency,Javafx,到目前为止,我一直在构建一个应用程序,其中工作线程在到达某个点或事件时,使用事件的时间戳millis更改StringProperty 反过来,JavaFX主线程中的侦听器侦听该属性,并将时间戳输出到GUI中的TextArea 在我的工作过程中,我不得不将工作线程的一些功能拆分为第二个工作线程,因为它有点太慢了 问题是:现在我有两个工作人员需要“玩”StringProperty,我得到了ConcurrentModification异常,正如预期的那样。 是否有任何方法或实现来处理这个问题,或者我必

到目前为止,我一直在构建一个应用程序,其中工作线程在到达某个点或事件时,使用事件的时间戳
millis
更改
StringProperty

反过来,JavaFX主线程中的侦听器侦听该属性,并将时间戳输出到GUI中的
TextArea

在我的工作过程中,我不得不将工作线程的一些功能拆分为第二个工作线程,因为它有点太慢了

问题是:现在我有两个工作人员需要“玩”StringProperty,我得到了
ConcurrentModification
异常,正如预期的那样。 是否有任何方法或实现来处理这个问题,或者我必须让第二个工作线程使用第二个StringProperty(并反过来将第二个侦听器附加到我的主线程,这是首选的)

编辑:对于请求倾听者的绅士,是这样的:

my_monitor.getMessageProperty().addListener(new ChangeListener<String>() {
    @Override
    public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
    //Substring because the last 13 digits is the current system milli time,
    //the measure is in place so that the observableValue always changes on an event.
        Platform.runLater(new Runnable() {
            @Override
            public void run() {
                writeToLog(newValue.substring(0, newValue.length() - 13));
            }
        });
    }
});
my_monitor.getMessageProperty().addListener(新的ChangeListener()){
@凌驾

public void已更改(observeValue您的第二种方法无论如何都不会起作用。如果您从后台线程修改
StringProperty
,将在该后台线程上调用观察它的侦听器,从而从后台线程更新您的
TextArea

相反,请使用
Platform.runLater()
更新FX应用程序线程上的(single)
StringProperty
。然后只能从FX应用程序线程访问字符串属性,因此它实际上是单线程的

更新:完整示例

import java.util.Random;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;

public class WorkerSharedPropertyExample extends Application {

    @Override
    public void start(Stage primaryStage) {
        final TextArea console = new TextArea();
        final BorderPane root = new BorderPane();
        root.setCenter(console);

        final Scene scene = new Scene(root, 600, 400);

        primaryStage.setScene(scene);
        primaryStage.show();

        final StringProperty messageHolder = new SimpleStringProperty();
        messageHolder.addListener(new ChangeListener<String>() {
            @Override
            public void changed(ObservableValue<? extends String> obs, String oldValue, String newValue) {
                console.appendText(newValue + "\n");
            }
        });

        Thread worker1 = createThread(messageHolder, "Worker 1");
        Thread worker2 = createThread(messageHolder, "Worker 2");

        worker1.start();
        worker2.start();
    }

    private Thread createThread(StringProperty messageHolder, String name) {
        final Random rng = new Random();
        Thread thread = new Thread() {
            @Override
            public void run() {
                int value = 0 ;
                try {
                    while (true) {
                        Thread.sleep(rng.nextInt(1000)+500);
                        value++; 
                        final String message = getName() + " updated status to value "+value ;
                        Platform.runLater(new Runnable() {
                            @Override
                            public void run() {
                                messageHolder.set(message);
                            }
                        });
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        };  
        thread.setName(name);
        thread.setDaemon(true);
        return thread ;
    }

    public static void main(String[] args) {
        launch(args);
    }
}
import java.util.Random;
导入javafx.application.application;
导入javafx.application.Platform;
导入javafx.beans.property.SimpleStringProperty;
导入javafx.beans.property.StringProperty;
导入javafx.beans.value.ChangeListener;
导入javafx.beans.value.observeValue;
导入javafx.scene.scene;
导入javafx.scene.control.TextArea;
导入javafx.scene.layout.BorderPane;
导入javafx.stage.stage;
公共类WorkerSharedPropertyExample扩展了应用程序{
@凌驾
公共无效开始(阶段primaryStage){
最终文本区域控制台=新文本区域();
最终边界窗格根=新边界窗格();
root.setCenter(控制台);
最终场景=新场景(根,600400);
初级阶段。场景(场景);
primaryStage.show();
final StringProperty messageHolder=新的SimpleStringProperty();
addListener(新的ChangeListener(){
@凌驾

public void已更改(observeValueYou真的得到了
ConcurrentModificationExceptions
?我只会在您使用集合时得到这些。我会在这里得到
IllegalStateException
s。第一种/第二种方法已经做到了。侦听器调用
Platform.runLater()
并在StringProperty发生更改时打印到TextArea。当然,第二种方法也会崩溃,因为它们都在编辑同一个StringProperty。检查我的问题,我添加了侦听器以方便您使用~您的方法不会更新FX应用程序线程上的
StringProperty
;它只是更新FX应用程序线程上的
TextArea
。如果使用
Platform.runLater(…)将更新移动到
StringProperty
到FX应用程序线程
在您的workers中,您可以避免字符串属性的任何潜在线程问题。我更新了一个完整的示例来演示。哦,明白了。我会在家里试用,如果它提供了一个稳定的解决方案,我会接受您的回答。非常感谢您的继续安装,亲爱的:33看起来正在工作,我会尽力保持它亲爱的,谢谢你,亲爱的。