Starting Synchronous Runnables
A synchronous runnable does not create its own thread to accomplish its tasks. It must use, or borrow, the thread that calls start() to execute the run() member. It is designed to pass control from the start() function to the internal run() function after performing any necessary initialization tasks.
Because run() is executed synchronously, start() cannot return control to its caller until run() returns control. This process is explained in the following steps and is illustrated in Figure 9.
1. When first constructed, a runnable object is initialized with an execution state of RW_THR_INITIAL[1] and a completion state of RW_THR_PENDING{1}.
2. The runnable briefly enters an execution state of RW_THR_STARTING[2] before entering its run() function, when the state is changed to RW_THR_RUNNING[3].
3. Once the runnable successfully completes its activities and returns from its run() function, the state reverts back to RW_THR_INITIAL[4] and start() returns a completion state of RW_THR_NORMAL{2}.
4. If an exception is thrown as a result of runnable activities and propagated back out of run(), the runnable enters the RW_THR_EXCEPTION[5] state before returning to the RW_THR_INITIAL[6] state and returning a completion state of RW_THR_FAILED{3}.
Figure 9 – Start operation for synchronous runnables — interaction and timing
You can start a synchronous runnable any number of times, but only one thread at a time can execute the encapsulated function within the runnable. If a second thread attempts to start a runnable that is currently being executed by another thread, the start() function produces an RWTHRThreadActive exception.