0

I need to perform a task every few hours and I'm looking for most efficient solution for that. I thought about two approaches:

1) busy waiting

while(true){

 doMyJob()
 wait(2*hour);

}

2) executor scheduling:

executor.schedule(new MyJobTask(),2,TimeUnit.HOUR);

...

class MyJobTask implements Runnable{

void run(){

 doMyJob();
 ...
 executor.schedule(new MyJobTask(),2,TimeUnit.HOUR);

}

Could you please advise me which solution is more efficient and in what situation each of them is more preferable (if any). Intuitively, I would go for second solution but I couldn't find anything to prove my intuition. If you have some other solutions - please share. Solution should be also memory efficient (that's why I have a dilemma - do I need to create and keep a ThreadPool object only to do a simple job every two hours).

Karusmeister
  • 871
  • 2
  • 12
  • 25
  • what EE spec do you have to work with? 1.4, 5 or 6? – fvu Jun 20 '12 at 16:31
  • Related: http://stackoverflow.com/questions/5357033/background-timer-task-in-jsp-servlet-web-application/5357856#5357856 Definitely don't do busy waiting. – BalusC Jun 20 '12 at 17:10

2 Answers2

3

None of the proposed solutions is really advisable inside an EE container (where you should avoid messing with threads), which you seem to target according to the tags of your question.

Starting with Java EE 5 there is the timer service which according to my tests works quite nicely with longer timeouts like the 2 hours in your example. There is one point that you really shouldn't forget though - quoting from the aforementioned tutorial:

Timers are persistent. If the server is shut down (or even crashes), timers are saved and will become active again when the server is restarted. If a timer expires while the server is down, the container will call the @Timeout method when the server is restarted.

If for whatever reason this solution is not acceptable you should have a look at the Quartz Scheduler. Its possibilities exceed your requirements by far, but at least it gives you a ready to use solution whose compatibility with a wide range of application servers is guaranteed.

fvu
  • 32,488
  • 6
  • 61
  • 79
1

Both should have about the same efficiency but I would suggest using ScheduledExecutorService

Executors.newSingleThreadScheduledExecutor()
    .scheduleAtFixedRate(new MyJobTask(), 0, 2, TimeUnit.HOUR);

There are several reasons, detailed here: A better way to run code for a period of time

But importantly, ScheduledExecutorService allows you to use multiple threads so that tasks which take a long time don't necessarily have to back-up your queue of tasks (the service can be running 2 of your tasks simultaneously). Also, if doMyJob throws an exception, ScheduledExecutorService will continue to schedule your task rather than being cancelled because it failed to reschedule the task.

Community
  • 1
  • 1
Jack Edmonds
  • 31,931
  • 18
  • 65
  • 77
  • This really doesn't feel like something I'd do in EJB. You think this won't create problems so you prefer this to EJB timer services? – esej Jun 20 '12 at 16:51