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看起来正在工作,我会尽力保持它亲爱的,谢谢你,亲爱的。