Package jmri.util

Class ThreadingUtil


  • @ThreadSafe
    public class ThreadingUtil
    extends java.lang.Object
    Utilities for handling JMRI's threading conventions.

    For background, see http://jmri.org/help/en/html/doc/Technical/Threads.shtml

    Note this distinguishes "on layout", for example, Setting a sensor, from "on GUI", for example, manipulating the Swing GUI. That may not be an important distinction now, but it might be later, so we build it into the calls.

    • Method Detail

      • runOnLayout

        public static void runOnLayout​(@Nonnull
                                       ThreadingUtil.ThreadAction ta)
        Run some layout-specific code before returning.

        Typical uses:

        ThreadingUtil.runOnLayout(() -> { sensor.setState(value); });

        Parameters:
        ta - What to run, usually as a lambda expression
      • runOnLayoutWithJmriException

        public static void runOnLayoutWithJmriException​(@Nonnull
                                                        ThreadingUtil.ThreadActionWithJmriException ta)
                                                 throws JmriException,
                                                        java.lang.RuntimeException
        Run some layout-specific code before returning. This method catches and rethrows JmriException and RuntimeException.

        Typical uses:

        ThreadingUtil.runOnLayout(() -> { sensor.setState(value); });

        Parameters:
        ta - What to run, usually as a lambda expression
        Throws:
        JmriException - when an exception occurs
        java.lang.RuntimeException - when an exception occurs
      • runOnLayoutEventually

        public static void runOnLayoutEventually​(@Nonnull
                                                 ThreadingUtil.ThreadAction ta)
        Run some layout-specific code at some later point.

        Please note the operation may have happened before this returns. Or later. No long-term guarantees.

        Typical uses:

        ThreadingUtil.runOnLayoutEventually(() -> { sensor.setState(value); });

        Parameters:
        ta - What to run, usually as a lambda expression
      • runOnLayoutDelayed

        @Nonnull
        public static javax.swing.Timer runOnLayoutDelayed​(@Nonnull
                                                           ThreadingUtil.ThreadAction ta,
                                                           int delay)
        Run some layout-specific code at some later point, at least a known time in the future.

        There is no long-term guarantee about the accuracy of the interval.

        Typical uses:

        ThreadingUtil.runOnLayoutDelayed(() -> { sensor.setState(value); }, 1000);

        Parameters:
        ta - what to run, usually as a lambda expression
        delay - interval in milliseconds
        Returns:
        reference to timer object handling delay so you can cancel if desired; note that operation may have already taken place.
      • isLayoutThread

        public static boolean isLayoutThread()
        Check if on the layout-operation thread.
        Returns:
        true if on the layout-operation thread
      • runOnGUI

        public static void runOnGUI​(@Nonnull
                                    ThreadingUtil.ThreadAction ta)
        Run some GUI-specific code before returning

        Typical uses:

        ThreadingUtil.runOnGUI(() -> { mine.setVisible(); });

        If an InterruptedException is encountered, it'll be deferred to the next blocking call via Thread.currentThread().interrupt()

        Parameters:
        ta - What to run, usually as a lambda expression
      • runOnGUIWithJmriException

        public static void runOnGUIWithJmriException​(@Nonnull
                                                     ThreadingUtil.ThreadActionWithJmriException ta)
                                              throws JmriException,
                                                     java.lang.RuntimeException
        Run some GUI-specific code before returning. This method catches and rethrows JmriException and RuntimeException.

        Typical uses:

        ThreadingUtil.runOnGUI(() -> { mine.setVisible(); });

        If an InterruptedException is encountered, it'll be deferred to the next blocking call via Thread.currentThread().interrupt()

        Parameters:
        ta - What to run, usually as a lambda expression
        Throws:
        JmriException - when an exception occurs
        java.lang.RuntimeException - when an exception occurs
      • runOnGUIwithReturn

        public static <E> E runOnGUIwithReturn​(@Nonnull
                                               ThreadingUtil.ReturningThreadAction<E> ta)
        Run some GUI-specific code before returning a value.

        Typical uses:

        Boolean retval = ThreadingUtil.runOnGUIwithReturn(() -> { return mine.isVisible(); });

        If an InterruptedException is encountered, it'll be deferred to the next blocking call via Thread.currentThread().interrupt()

        Type Parameters:
        E - generic
        Parameters:
        ta - What to run, usually as a lambda expression
        Returns:
        the value returned by ta
      • runOnGUIEventually

        public static void runOnGUIEventually​(@Nonnull
                                              ThreadingUtil.ThreadAction ta)
        Run some GUI-specific code at some later point.

        If invoked from the GUI thread, the work is guaranteed to happen only after the current routine has returned.

        Typical uses:

        ThreadingUtil.runOnGUIEventually( ()->{ mine.setVisible(); } );

        Parameters:
        ta - What to run, usually as a lambda expression
      • runOnGUIDelayed

        @Nonnull
        public static javax.swing.Timer runOnGUIDelayed​(@Nonnull
                                                        ThreadingUtil.ThreadAction ta,
                                                        int delay)
        Run some GUI-specific code at some later point, at least a known time in the future.

        There is no long-term guarantee about the accuracy of the interval.

        Typical uses:

        ThreadingUtil.runOnGUIDelayed( ()->{ mine.setVisible(); }, 1000);

        Parameters:
        ta - What to run, usually as a lambda expression
        delay - interval in milliseconds
        Returns:
        reference to timer object handling delay so you can cancel if desired; note that operation may have already taken place.
      • isGUIThread

        public static boolean isGUIThread()
        Check if on the GUI event dispatch thread.
        Returns:
        true if on the event dispatch thread
      • newThread

        public static java.lang.Thread newThread​(java.lang.Runnable runner)
        Create a new thread in the JMRI group
        Parameters:
        runner - Runnable.
        Returns:
        new Thread.
      • newThread

        public static java.lang.Thread newThread​(java.lang.Runnable runner,
                                                 java.lang.String name)
        Create a new thread in the JMRI group.
        Parameters:
        runner - Thread runnable.
        name - Thread name.
        Returns:
        New Thread.
      • getJmriThreadGroup

        public static java.lang.ThreadGroup getJmriThreadGroup()
        Get the JMRI default thread group. This should be passed to as the first argument to the Thread constructor so we can track JMRI-created threads.
        Returns:
        JMRI default thread group.
      • canThreadRun

        public static boolean canThreadRun​(@Nonnull
                                           java.lang.Thread t)
        Check whether a specific thread is running (or able to run) right now.
        Parameters:
        t - the thread to check
        Returns:
        true is the specified thread is or could be running right now
      • isThreadWaiting

        public static boolean isThreadWaiting​(@Nonnull
                                              java.lang.Thread t)
        Check whether a specific thread is currently waiting.

        Note: This includes both waiting due to an explicit wait() call, and due to being blocked attempting to synchronize.

        Note: canThreadRun(Thread) and isThreadWaiting(Thread) should never simultaneously be true, but it might look that way due to sampling delays when checking on another thread.

        Parameters:
        t - the thread to check
        Returns:
        true is the specified thread is or could be running right now
      • requireGuiThread

        public static void requireGuiThread​(org.slf4j.Logger logger)
        Check that a call is on the GUI thread. Warns (once) if not. Intended to be the run-time check mechanism for @InvokeOnGuiThread

        In this implementation, this is the same as requireLayoutThread(org.slf4j.Logger)

        Parameters:
        logger - The logger object from the calling class, usually "log"
      • requireLayoutThread

        public static void requireLayoutThread​(org.slf4j.Logger logger)
        Check that a call is on the Layout thread. Warns (once) if not. Intended to be the run-time check mechanism for @InvokeOnLayoutThread

        In this implementation, this is the same as requireGuiThread(org.slf4j.Logger)

        Parameters:
        logger - The logger object from the calling class, usually "log"
      • warnLocks

        public static void warnLocks()
        Warn if a thread is holding locks. Used when transitioning to another context.