Periodic Thread Processing in Java
In an earlier blog where I discussed how to handle uncaught Java exceptions in other threads, I had a minor bug in my example code. Although it wasn't the point of the example, the code had intended to perform some processing once per second. In reality, the code I wrote performed its processing, then waited one second to begin it again. Technically this wasn't once per second since it didn't take into account the time spent doing the actual processing.
More Insights
White Papers
More >>Reports
More >>Webcasts
- Catch the Security Breach Before It’s Out of Reach
- New Technologies to Optimize Mobile Financial Services
To be more exact, the code should instead sleep for a total of 1000 milliseconds minus the number of milliseconds the processing takes. This assumes, of course, that the processing lasts less than 1000 milliseconds, but let's assume that's always the case for the time being. However, to be as precise as possible, you really need to turn to alternatives such as real-time Java, and specifically, a JVM that implements the Real-Time Specification for Java (RTSJ).
Quick, What Is Real-Time?
The Real-Time Specification for Java defines how Java should behave in a real-time computing context. However, what does real-time really mean? There are many misunderstandings about what real-time is, even amongst seasoned enterprise Java developers. Some confuse it with high performance, or fast, computing. Others use it to describe dynamic applications such as instant messaging or data-feed processing. Neither one is necessarily an example of a real-time system.
Therefore, real-time does not always equal real fast, although good performance is often desirable and achievable. As for a quick definition, the goal of a real-time system is to respond to real-world events predictably, before a measurable deadline, or within a bounded time frame. Of course, it gets a little more complicated in terms of the details, but that's the basic foundation. For an in-depth understanding of real-time systems and the RTSJ, check out my book, Real-Time Java Programming.
Periodic Real-Time Threads
Let's skip ahead to a better solution to the "perform some processing every n
milliseconds (or some other timeframe)" problem, and see how real-time Java can help. The RTSJ defines the javax.realtime.RealtimeThread
class, which extends the base Java Thread
class, but adheres to strict real-time scheduling. With it, you define a priority — within the real-time class of priorities — and optionally a release schedule. This schedule dictates when, precisely, the RTT will be released, or stated simply, scheduled to begin or resume execution. A periodic real-time Thread
is one that uses the javax.realtime.PeriodicParameters
class to define its release schedule. The code below illustrates this, using the RTSJ:
import javax.realtime.*; public class ReactorCore { // Embedded temperature gauge class class TempGauge extends RealtimeThread { public TempGauge(SchedulingParameters sched, ReleaseParameters rel) { super(sched, rel); // call RealtimeThread constructor } public void run() { while ( true ) { // Check reactor temp here... ... boolean ok = waitForNextPeriod(); if ( ! ok ) { // Handle deadline miss here... } } } } private TempGauge temp = null; //////////////////////////////////////////////////////////// public ReactorCore() { // Run at highest priority PriorityParameters sched = new PriorityParameters( PriorityScheduler.instance().getMaxPriority()); // 1 millisecond periodic release ReleaseParameters rel = new PeriodicParameters( new RelativeTime(1,0) ); temp = new TempGauge(sched, rel); temp.start(); // ... } public static void main(String[] args) { ReactorCore core = new ReactorCore(); } }
In this example, we define RTT TempGauge
to periodically check the temperature of a reactor core once per millisecond. First, as defined by the PriorityParameters
in the ReactorCore
class constructor, the RTT is set to run at the highest priority. Second, as defined by the ReleaseParameters
, our RTT will be released to execute exactly once per millisecond. Thanks to the RTSJ, the compliant JVM we're to use here will employ high-resolution timers to guarantee that this thread will be released precisely once per millisecond; no more, no less. To ensure this, the RTT must perform its processing and then finish with a call to waitForNextPeriod
, which will wait for whatever time is remaining before the next release period. This calculation is handled for you by the real-time JVM — no need to do this yourself. This means that regardless of processing time — so long as it's less than one millisecond — TempGauge
RTT will be released and begin processing at one-millisecond boundaries precisely. This is illustrated in the figure below.
As with our code above, thread T1
in this figure has a one-millisecond period, and is released on each one-millisecond time boundary regardless of its processing time per release. The call to waitForNextPeriod
ensures this by working with the priority scheduler within the RTSJ-compliant Java VM.
Other RTSJ Facilities
The RTSJ defines other real-time behavior, such as:
- Aperiodic
RealtimeThreads
: RTTs that don't have minimum or maximum wait times between releases, useful for waiting on resources, for example NoHeapRealtimeThread
: RTTs that never access the heap, and hence are never subject to garbage collection delays, interruptions, or released latencies- Real-time memory management: real-time behavior through the use of non-heap memory regions such as
ImmortalMemory
orScopedMemory
- Asynchronous event handling: the ability to schedule processing to occur when some outside event occurs
- Asynchronous transfer of control or thread termination: safe shift of execution from one RTT to another, or safe RTT termination, based on an event or
Exception
- Physical Memory Access: byte-level access to physical memory regions to allow direct communication with hardware devices, where supported.
To read all about the RTSJ and how to code real-time systems in Java, check out my book on the subject, and stay tuned to my blog as I explore this further in the future.
Happy coding!
-EJB