views:

183

answers:

1

I'm scheduling a task using a ScheduledThreadPoolExecutor object. I use the following method:

public ScheduledFuture<?> schedule(Runnable command, long delay,TimeUnit unit) 

and set the delay to 30 seconds (delay = 30,000 and unit=TimeUnit.MILLISECONDS). Sometimes my task occurs immediately and other times it takes 70 seconds.

I believe the ScheduledThreadPoolExecutor uses CPU specific clocks. When i run tests comparing System.currentTimeMillis(), System.nanoTime() [which is CPU specific] i see the following

schedule: 1272637682651ms, 7858346157228410ns

execute: 1272637682667ms, 7858386270968425ns

difference is 16ms but 4011374001ns (or 40,113ms)

so it looks like there is discrepancy between two CPU clocks of 40 seconds

How do i resolve this issue in java code? Unfortunately this is a clients machine and i can't modify their system.

+1  A: 

Yes, you're right that ScheduledThreadPoolExecutor uses System.nanoTime(). And you're also right that System.nanoTime() is dependent on the particular system instance. If your process happens to migrate between schedule and execute, then you're out of luck. (I wouldn't think that migrating between CPUs on a multi-CPU system would matter, but maybe it does? Certainly it would matter if you're running in a VM and the VM migrated between hosts).

I think the only real solution in this case is to use something other than ScheduledThreadPoolExecutor... It's not a simple as just changing ScheduledThreadPoolExecutor.now() either. AbstractQueuedSynchronizer$ConditionObject.awaitNanos() uses System.nanoTime() too.

One of my projects uses Quartz for job scheduling and I've never seen the problem you describe with that library. I don't know the implementation details (maybe it just uses System.nanoTime() too, but maybe not?).

Chris Dolan