简体   繁体   中英

Is an AtomicBoolean overkill in this code?

Here is some code I have written to handle in a generic fashion an event handler which should only fire once for any JavaFX event:

public final class OneShotEvent<T extends Event>
    implements EventHandler<T>
{
    private final AtomicBoolean triggered = new AtomicBoolean(false);
    private final EventHandler<T> delegate;

    public static <E extends Event> EventHandler<E> of(final EventHandler<E> delegate)
    {
        return new OneShotEvent<>(delegate);
    }

    private OneShotEvent(final EventHandler<T> delegate)
    {
        this.delegate = Objects.requireNonNull(delegate);
    }

    @Override
    public void handle(final T event)
    {
        if (!triggered.getAndSet(true))
            delegate.handle(event);
    }
}

For some reason, I made triggered an AtomicBoolean instead of a plain boolean .

After thinking about it, I believe this is overkill, because event handlers will run on the "platform thread" of JavaFX... Or will they not? Because if this is the case, then a simple boolean is enough... Right?

If you know the calls are single threaded or thread safe, a simple boolean would be enough, though your could drop it.

private EventHandler<T> delegate;

public void handle(T event) {
    if (delegate != null)
        delegate.handle(event);
    delegate = null; // don't retain a delegate we don't need
}

After thinking about it, I believe this is overkill, because event handlers will run on the "platform thread" of JavaFX... Or will they not?

Yes, they will:

The JavaFX scene graph, which represents the graphical user interface of a JavaFX application, is not thread-safe and can only be accessed and modified from the UI thread also known as the JavaFX Application thread.

If you are sure the event handler runs on the application thread, you don't need to care about thread safety.

However events can also run on a non-application thread. The thread firing the event is also the thread running the event handler.

You can demonstrate this with the following code, that doesn't even start up the application thread:

public class EventThreadsTest {

    public static void main(String[] args) {
        Thread t = Thread.currentThread();
        EventHandler handler = (evt) -> {
            System.out.println("Application thread: " + Platform.isFxApplicationThread());
            System.out.println("main thread: " + Thread.currentThread() == t);
        };
        Node target = new Pane();
        target.setOnMouseClicked(handler);
        target.fireEvent(new MouseEvent(MouseEvent.MOUSE_CLICKED, 0, 0, 0, 0, MouseButton.PRIMARY, 1, true, true, true, true, true, true, true, true, true, true, null));
    }

}

Output:

Application thread: false
main thread: true

However UI events like Button.onAction and Node.onMouseClicked triggered by user interaction run on the application thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM