Using while(true)
and TimeUnit.SECONDS.sleep
is a possibility, but it is bad practice (as you can see from the sheer number of downvotes on this post). This SO answer gives some reasons as to why:
- low level, subject to spurious wakeups
- clock drift
- control
- intent of code
there are others.
The basic way to achieve this is to use a java.util.Timer
, not to be confused with a javax.swing.Timer
:
final Timer timer = new Timer("MyTimer");
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println(System.currentTimeMillis());
}
}, 0, TimeUnit.SECONDS.toMillis(1));
You need to call timer.cancel()
to stop the timer - as the timer is running a non-daemon thread your program will not exit until that is done.
A more advanced way, which allows multiple tasks to be scheduled to run at different intervals on a pool of the ScheduledExecutorService
. This allows you to scheduleAtFixedRate
which runs a task every second (regardless of how long it takes to run, i.e. the gap between start times is always the same) or scheduleWithFixedDelay
which runs a task at one second intervals (i.e. the gap between the end of one run and the start of the next is always the same).
For example:
final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
final ScheduledFuture<?> handle = executorService.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println(System.currentTimeMillis());
}
}, 0, 1, TimeUnit.SECONDS);
To cancel the particular task you would call handle.cancel(false)
(as interrupting has no effect) and to stop the executorService
you would call executorService.shutdown()
after which you might want to add a executorService.awaitTermination(1, TimeUnit.DAYS)
to wait for all the tasks to finish.
EDIT
A comment This can be done more concisely in java 8 with lambda right? (not an expert at lambdas)
The first example, no. A Timer
takes a TimerTask
, this is an abstract class
and not an @FunctionalInterface
so a lambda is not possible. In the second case, sure:
final ScheduledFuture<?> handle = executorService.
scheduleAtFixedRate(() -> System.out.println(System.currentTimeMillis()), 0, 1, TimeUnit.SECONDS);