Here's my simple code to loop every second (doesn't need to be exact) and kick off a job if necessary:
while (true) {
// check db for new jobs and
// kick off thread if necessary
try {
Thread.sleep(1000);
} catch(Throwable t) {
LOG.error("", t);
}
}
This code has worked fine for several months. Just yesterday we started having problems where one of our servers seems to be hung in the Thread.sleep(1000) method. IOW - it's been over a day and the Thread.sleep hasn't returned. I started up jconsole and get this info about the thread.
Name: Thread-3
State: TIMED_WAITING
Total blocked: 2 Total waited: 2,820
Stack trace:
java.lang.Thread.sleep(Native Method)
xc.mst.scheduling.Scheduler.run(Scheduler.java:400)
java.lang.Thread.run(Thread.java:662)
Scheduler.java:400 is the Thread.sleep line above. The jconsole output doesn't increment "Total waited" every second as I'd expect. In fact it doesn't change at all. I even shut down jconsole and started it back up in the hopes that maybe that would force a refresh, but only got the same numbers again. I don't know what other explanation there could be besides that the jvm has incorrectly hung on the sleep command. In my years, though, I've had so few problems with the jvm that I assume it must be an oversight on my part.
note: The other thing to note is that no other thread is active. IOW - the cpu is nearly idle. I read somewhere that Thread.sleep could be legitimately starved if another thread was active, but that isn't the case here.
solaris version:
$ uname -a
SunOS xcmst 5.10 Generic_141415-08 i86pc i386 i86pc
java version:
$ java -version
java version "1.6.0_26"
Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
Java HotSpot(TM) Server VM (build 20.1-b02, mixed mode)
Suspends the current thread for the specified number of milliseconds. Suspends the current thread for the specified amount of time.
Thread. sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system.
To be more clear: Threads consume no CPU at all while in not runnable state. Not even a tiny bit. This does not depend on implementation.
The code would only execute when someXThread was executing, in which case telling someYThread to yield would be pointless. So since the only thread worth calling yield on is the current thread, they make the method static so you won't waste time trying to call yield on some other thread.
In addition to what bdonlan mentioned you may want to look into ScheduledThreadPoolExecutor. I work on a very similar type of project and this object has made my life easier, thanks to this little snippet.
If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
I hope this helps!
Are you depending on the system tick count to increase monotonically?
From what I've heard from someone experienced, it (occasionally) happens that the system tick goes backwards by one or two ticks. I haven't experienced it myself yet, but if you're depending on this, might this explain what's happening?
When I said System.currentTimeMillis()
, I believe I was mistaken. I thought that System.currentTimeMillis()
is similar to Windows' GetTickCount()
function (i.e. it is measures a time that is independent of the system time), but in fact, that does not seem to be the case. So of course it can change, but that was not my point: apparently, tick counts measured by the system timer can also go backwards by a tick or two, even ignoring system time changes. Not sure if that helps, but thanks to Raedwald for pointing out the system time change possibility, since that's not what I meant.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With