Your assumptions are incorrect: there is no flow associated with adding listeners to properties.
JavaFX properties are basically an implementation of the Observer Pattern . The implementation used is rather complicated, because these properties support a "lazy evaluation", which means that other objects can be notified that the current value is no longer valid, but without recalculating the value, unless it is requested.
However, the basic idea is very simple: the property simply stores a list of listeners and notifies them if the set method is called. The following code does not match how StringProperty is implemented in the library, but it will give you an idea of โโwhat is going on:
public class ExampleStringProperty { private final List<ChangeListener<? super String>> changeListeners = new ArrayList<>(); private String value ; public String get() { return value ; } public void set(String value) { if (! Objects.equals(value, this.value)) { String oldValue = this.value ; this.value = value ; for (ChangeListener<? super String> listener : changeListeners) { listener.changed(this, oldValue, value); } } } public void addListener(ChangeListener<? super String> listener) { changeListeners.add(listener); } public void removeListener(ChangeListener<? super String> listener) { changeListeners.remove(listener); } }
As you can see, the thread is not involved: if the property is set, the listener methods changed(...) are called on the same thread.
Here is a quick test using the actual SimpleStringProperty from the library:
import javafx.beans.property.SimpleStringProperty; import javafx.beans.property.StringProperty; public class StringPropertyTest { public static void main(String[] args) { StringProperty prop = new SimpleStringProperty(); prop.addListener((obs, oldValue, newValue) -> { System.out.printf("Property changed from %s to %s on thread %s%n", oldValue, newValue, Thread.currentThread()); }); System.out.println("Running on thread "+Thread.currentThread()); System.out.println("Setting property to \"value\""); prop.set("value"); System.out.println("Setting property to \"new value\" on thread "+Thread.currentThread()); prop.set("new value"); } }
which produces the output
Running on thread Thread[main,5,main] Setting property to "value" Property changed from null to value on thread Thread[main,5,main] Setting property to "new value" on thread Thread[main,5,main] Property changed from value to new value on thread Thread[main,5,main]