Reputation: 2593
I'm tryng to write a simple Java program that runs some code every hour when the minute hand is at 20. The issue is that that the way I'm doing it is incredibly CPU intensive. I'm familiar with Quartz but I'm looking for a much simpler solution, any ideas?
boolean run = true;
while(run){
Calendar calendar = new GregorianCalendar();
int minute = calendar.get(Calendar.MINUTE);
if(minute == 20){
//Do some Stuff
}
}
Upvotes: 3
Views: 8988
Reputation: 235984
Be aware that if your application is running inside a managed environment (a web or ejb container) you're not allowed to use Thread.sleep()
or any other thread-related operations, for that matter, take a look at the EJB restrictions page. I warn about this because the question is tagged java-ee
, so the "simple application" might not be so simple after all - if it's running inside a Java EE container there are additional considerations to take care of.
If you're building an enterprise-grade application, forget about Thread.sleep()
. Go for a full-fledged job scheduler, Use Quartz, it's an open source and extremely mature and reliable product. Or use Obsidian Scheduler, a feature-rich commercial scheduler with more out-of-the-box features than Quartz.
A lightweight alternative to a full-fledged scheduler (but suitable for running inside a container) would be to use the Timer service.
Upvotes: 2
Reputation: 1104
I would suggest that you remove the scheduling logic from your java program.
By doing this you are able to focus only on what you want your program to do and leave the scheduling part to the OS.
Also, say for example you decide at some point to write a c++ program that does what your java code does know, you won't have to implement the cron logic in your new program
That being said:
Upvotes: 1
Reputation: 7625
Yet even another example with the things learned today.
import java.util.Calendar;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class SchedulerExample2 implements Runnable{
public static void main(String args[]) {
Calendar due = Calendar.getInstance();
due.set(Calendar.MILLISECOND, 0);
due.set(Calendar.SECOND, 0);
due.set(Calendar.MINUTE, 20);
if (due.before(Calendar.getInstance())) {
due.add(Calendar.HOUR, 1);
}
long milliSecondsToNextOcurrence = due.getTimeInMillis() - new Date().getTime();
final ScheduledExecutorService s = Executors.newSingleThreadScheduledExecutor();
ShedulerExample task = new ShedulerExample();
s.scheduleAtFixedRate(task, milliSecondsToNextOcurrence, 60*60*1000, TimeUnit.MILLISECONDS);
}
@Override
public void run() {
System.out.println("hola->"+new Date());
}
}
Upvotes: 0
Reputation: 7625
Another example
import java.text.SimpleDateFormat;
import java.util.Date;
public class TestHour {
private static final int MINUNTE = 20;
public static void main(String args[]) {
while (true) {
SimpleDateFormat bartDateFormat = new SimpleDateFormat("mm");
Date date = new Date();
int currentMin = new Integer(bartDateFormat.format(date))
.intValue();
if (currentMin < MINUNTE) {
sleepMinutes(MINUNTE - currentMin);
} else if (currentMin > MINUNTE) {
sleepMinutes(60 - currentMin + MINUNTE);
} else {
// DO SOMETHING EVERY HOUR
System.out.println("come on do it!!!");
sleepMinutes(60);
}
}
}
private static void sleepMinutes(int minutes) {
try {
System.out.println("Sleeping for " + minutes);
Thread.sleep(minutes * 1000*60);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Upvotes: 0
Reputation: 200138
A simple solution is to use the Executors framework:
final ScheduledExecutorService s = Executors.newSingleThreadScheduledExecutor();
s.scheduleAtFixedRate(task, secondsToFirstOccurence, 60*60, TimeUnit.SECONDS);
And use some logic to find out secondsToFirstOccurence
. This will probably involve a Calendar
instance, but would be much more convenient with JodaTime.
Upvotes: 5
Reputation: 30097
1) On first entry calculate next due time.
2) Use java.util.Timer.schedule()
3) Reschedule each run.
Code
package tests;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class App201210130040 {
private static Timer timer = new Timer(false);
public static void schedule() {
Calendar due = Calendar.getInstance();
due.set(Calendar.MINUTE, 20);
if( due.before(Calendar.getInstance()) ) {
due.add(Calendar.HOUR, 1);
}
System.out.println("Scheduled to " + due.getTime().toString());
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("due");
schedule();
}
}, due.getTime());
}
public static void main(String[] args) {
schedule();
}
}
Upvotes: 0
Reputation: 19368
So definitely the ScheduledExecutorService is fantastic as many of the other answers state.
In the event you're in a Java EE 6 server, you could have some fun with @Schedule
and ScheduleExpression
See Have an EJB schedule tasks with "crontab syntax"
Upvotes: 0
Reputation: 638
Use something like this
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY, 20);
calendar.set(Calendar.MINUTE, 20);
calendar.set(Calendar.SECOND, 0);
Date time = calendar.getTime();
Timer timer = new Timer();
timer.schedule(new SomeTask(), time);
and then reschedule
Upvotes: 0
Reputation: 19185
You should have a look at ScheduledExecutorService
class BeeperControl {
private final ScheduledExecutorService scheduler =
Executors.newScheduledThreadPool(1);
public void beepForAnHour() {
final Runnable beeper = new Runnable() {
public void run() { System.out.println("beep"); }
};
final ScheduledFuture<?> beeperHandle =
scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS);
scheduler.schedule(new Runnable() {
public void run() { beeperHandle.cancel(true); }
}, 60 * 60, SECONDS);
}
}
Upvotes: 0
Reputation: 240860
Schedule a cron job for the method that you want to execute hourly rather going for blocking sleep()
call, Use some scheduling framework like quartz
Upvotes: 0
Reputation: 3650
Put your code in an infinite while and use
Thread.sleep(3600000);
Start the execution at 20 after
Example
while(1==1) {
//Your code here
try{
Thread.sleep(3600000);
}
catch (Exception e) {}
}
Upvotes: 0