Reputation: 277
I'm having a few issues with scheduling a task to run in my code every minute.
I have tried many ways to do this such as:
Timer timer = new Timer();
timer.schedule( new TimerTask() {
public void run() {
printTime();
}
}, 0, 60*1000);
And also:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () -> {
printTime();
};
executor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.MINUTES);
These both print out erratic times not even close to the times I have provided:
2019-12-03T12:48:23.300
2019-12-03T12:48:24.700
2019-12-03T12:48:41.895
2019-12-03T12:48:42.799
2019-12-03T12:48:47.189
2019-12-03T12:48:47.211
2019-12-03T12:48:47.278
These are the times I get, totally wrong and some are within seconds! Is there an accurate way for me to schedule a task to run every minute while my code preforms other tasks?
My plan was to calculate the times between when the task is fired but Timer and ScheduledExecutor seems to wait longer than the time provided also not only shorter. So this means it would also be off.
Upvotes: 0
Views: 1453
Reputation: 366
I run below code and it is working as expected
public class Test {
public static void main(String[] args) {
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () -> printTime();
executor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.MINUTES);
}
private static void printTime() {
System.out.println(new Date());
}
}
Output is:
Tue Dec 03 16:06:31 EET 2019
Tue Dec 03 16:07:31 EET 2019
Tue Dec 03 16:08:31 EET 2019
Tue Dec 03 16:09:31 EET 2019
Probably, you are running multiple instance of TimerTask. You can extract your code to an utility class to ensure you have only one instance.
public enum PrintTimer {
INSTANCE;
private boolean running = false;
private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
public synchronized void start() {
if (!running) {
running = true;
Runnable task = () -> printTime();
executor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.MINUTES);
}
}
private static void printTime() {
System.out.println(LocalDateTime.now());
}
}
You can call it like:
PrintTimer.INSTANCE.start();
Upvotes: 2
Reputation: 1772
Both of them works
Runnable task = () -> System.out.println("Executor: " + LocalDateTime.now());
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleWithFixedDelay(task, 0, 1, TimeUnit.MINUTES);
and
new Timer().schedule(new TimerTask() {
public void run() {
System.out.println("Timer: " + LocalDateTime.now());
}
}, 0, 60*1000);
Output
Timer: 2019-12-03T15:29:25.931
Executor: 2019-12-03T15:29:25.931
Timer: 2019-12-03T15:30:25.904
Executor: 2019-12-03T15:30:25.934
Timer: 2019-12-03T15:31:25.904
Executor: 2019-12-03T15:31:25.935
Timer: 2019-12-03T15:32:25.905
Executor: 2019-12-03T15:32:25.937
If you can choose, better use ScheduledExecutorService
(Java Timer vs ExecutorService)
Upvotes: 1