Software documentation

Development tools


Techniques and Standards

How To

Functional Info

Background Info

JMRI: Threading

The vast majority of JMRI code (and programmers) don't have to worry about threading. Their code gets invoked, and invokes other code, and threading takes care of itself. This is particularly true of event-based code, which responds to events from e.g. the GUI or a layout object changing, and calls methods on other objects, which may in turn create more events.

This simplicity comes from using a single thread for processing most of JMRI's activity: The Java Swing event thread.

Note that this does not mean that other things can't be happening. For example, this script fragment:

    state = sensors.provideSensor("mySensor").getState()
print state == sensors.provideSensor("mySensor").getState()
can print either true or false, because changing that turnout can change associated sensors instantaneously.

There are times when you might want to do something a bit more complex using an additional thread:

We would prefer that you handle the threading issues that arise in that case via the jmri.util.ThreadingUtil class. ThreadingUtil provides utilities that make it easy to invoke needed functions on the right thread.

For example, if you want to read a bunch of data from a file, spend some time munging it, and then create a window to present it all, you might want to do all that work on a separate thread. At the end, when it's time to set your new frame visible, you have to to that on the Swing (GUI) thread. Here's the code to do that:

    frame = new JmriJFrame();  // frame declared as instance variable
// spend a long time reading data and configuring the frame
ThreadingUtil.runOnGUI( ()->{ frame.setVisible(); });
ThreadingUtil separates operations on the GUI (e.g. Java Swing) thread, and operations on the Layout (e.g. Sensors, Turnouts, etc) thread. There's no real difference now, but in the interest of perhaps someday needing to separate those, we've introduced the two versions now. Please try to pick the mostly-likely-right one when coding.

(N.B.: You'll find lots of older cases that use explicitly use javax.swing.SwingUtilities.invokeLater(r) or javax.swing.SwingUtilities.invokeAndWait(r); these should be migrated to the newer JMRI-specific methods as time is available to keep our code just a tiny bit cleaner and more flexible.)