0

I want to schedule an event to happen at a particular time, regardless of whether the computer suspends in the meanwhile. If computer is suspended when the event should have occurred, I want it to be scheduled immediately on resume.

I tried two ways: a thread with a sleep(), and a Swing Timer. Both these methods rely on a timed delay, and both suffer the same problem in that the delay countdown is suspended when the computer suspends, and continues only when the computer resumes, so the event occurs at (original delay + time suspended).

I then guessed that what I should be doing is to use a (util) Timer with a target Date, as this specifies a point in time, like so:

Date targetDate = new Date(System.currentTimeMillis() + (60 * 1000)); // in 1 min
Timer eventTimer = new Timer();
eventTimer.schedule(eventThread, targetDate);

Unfortunately this suffers in exactly the same way.

I did also look at the ScheduledExecutorService (although overkill for this application I thought) but it explicitly uses delays, so I assumed it would suffer the same problem.

Is what I want to do possible?

ceperman
  • 405
  • 2
  • 8
  • http://stackoverflow.com/questions/409932/java-timer-vs-executorservice?rq=1 as you can see here, it is recommended to use executors instead of timers (it is also quite simple to use them) – ovdsrn Nov 08 '14 at 11:08
  • @ovdsm generally good advice maybe, but I tried it and as suspected, suffers the same problem. – ceperman Nov 08 '14 at 12:22

2 Answers2

1

the delay countdown is suspended

No, this is not really what happens. Otherwise it would mean the system time would be wrong on resume!

Is what I want to do possible?

Here is a solution:

  • have one task handle all the scheduling, which runs, say, every second;
  • in a task to be executed, record the time, make the class of your task Comparable against the expected execution time;
  • put all these tasks in a PriorityQueue (or even a PriorityBlockingQueue);
  • when the scheduling task wakes up, peek the tasks; if the expected execution time is less than, or equal, to the current time, dequeue it and execute it; repeat until the peeked task has an expected execution time greater than the current time.

This will not make for "immediate execution upon resume", but close to.

fge
  • 119,121
  • 33
  • 254
  • 329
  • A similar solution had occurred to me also, but I was hoping that some timer option could make it work the way I expected. If no other suggestion comes up, this is what I'll have to do. Thanks. BTW "the delay countdown is suspended" is indeed really what happens, by inspection. This doesn't suggest or imply anything about the maintenance of "system time" - I imagine the two have quite independent implementations. – ceperman Nov 08 '14 at 15:09
0

Things are even weirder. I have a program that refreshes data on an hourly basis, using java.util.Timer and a suitable TimerTask. With openSuse up to version 13.1 that program worked as required - when due to a suspend the real time exceeded the cycle, the task was called "immediately" after the resume. Running the same program with the same jvm (1.8.0_40-b10) and the same Linux kernel (3.14.24), but with openSuse 13.2, the task is not called on resume but only after the period has expired in wake mode. I have solved this problem by calling the task via a function key if the current time exceeds the scheduled time and resynchronizing the task if necessary. That's a nuisance but acceptable because the resume is anyway done via a key stroke.

harald
  • 41
  • 2