java timers: how to select + what are the limitations?
I need to write some code to stress-test RS232 communication using rxtx (note: this question is NOT about serial communications, so please don't go there), and I would like to periodically send bytes using some kind of timer task.
Are there any kind of guidelines online about what kind of timer class to use for various applications? I'm not sure whether I should use javax.swing.Timer or java.util.Timer or java.util.concurrent.ScheduledExecutorService or something else.
Also at what frequency do they start to break down? I would guess that it's along the lines of the operating system timeslice (forget what it is in Windows, 1msec-10msec seems about what I remember). I want to run at the fastest frequency that will not give me problems on my PC; I can always spit out more bytes out my serial port at a time, I'd just like to do it in as much of a periodic fashion as I can.
Don't use the Swing timer; that's a kluge from early Swing days.
The ScheduledExecutorService is the more general and configurable of the two remaining contenders. It accepts nanosecond precision, but of course cannot provide any better than milisecond accuracy depending on platform. You'd need a real-time JVM for nanosecond accuracy.
If you want a high frequency yet accurate frequency, I wouldn't use a timer.
I did something much like this once in Delphi, providing quick pulses to a stepper motor. I was at liberty to chew up as much CPU time as I wanted for this, so I ran a tight loop that checked Windows' high precision timer until the right amount of time had passed, and then did the action I needed.
It's not quite as convenient in Java, but I'd recommend a similar approach, using System.nanoTime().
You may find you missed the last time mark. If so, deal with it somehow. Either hurry and do your action anyway, or do whatever needs doing to compensate for the error - maybe wait for an entire character space to pass, or whatever. Also, you may want to modify the time interval to the next event. Whatever it takes to accurately deal with the normal jitter, in other words.
If you don't do a lot of object creation in your loop, there's no sensible reason why your garbage collector should kick in, so your timing has a reasonable chance of remaining accurate.
Jonathan Feinberg admonishes me that ScheduledExecutorService is made for this kind of thing. I contend that it's not suitable for the high-frequency, high precision requirement of the OP.
I have a link here from someone complaining in a Sun forum about accuracy problems using this technique: His repeat rate is only 200 ms and yet he's experiencing delays of over 1 second!
Problem with the Java way of doing this is that it's using the operating system's facilities for doing this in a mostly cross-platform manner, and in a way that won't negatively impact the rest of the system. These are compromises; when you have a priority on getting a lot of events out fast and accurately, and you have some leeway on the constraints, it is possible to construct a solution that works better. This is exactly what I've outlined.