-4

I want to create a thread which never halts. Every second it will acquire the system time and display this on the console. This is what I have so far:

public class Test implements Runnable {

    @Override
    public void run() {
        System.out.println(System.currentTimeMillis());
    }
}

I'd like to avoid using a loop.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483

1 Answers1

2

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);
Community
  • 1
  • 1
Boris the Spider
  • 59,842
  • 6
  • 106
  • 166
  • This can be done more concisely in java 8 with lambda right? (not an expert at lambdas) – Cruncher Jul 23 '14 at 07:06
  • @AshishSrivastava what did I say? Make sure you are **not** using a `javax.swing.Timer`! – Boris the Spider Jul 23 '14 at 07:10
  • @Cruncher added something on that. – Boris the Spider Jul 23 '14 at 07:13
  • @AshishSrivastava what is the _exact_ compiler error you are getting? – Boris the Spider Jul 23 '14 at 07:14
  • import java.util.Timer; public class Test implements Runnable { final Timer timer = new Timer("MyTimer"); timer.schedule(new TimerTask() { @Override public void run() { System.out.println(System.currentTimeMillis()); } }, 0, TimeUnit.SECONDS.toMillis(1)); } illegal start expression – Ashish Srivastava Jul 23 '14 at 07:17
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/57810/discussion-between-ashish-srivastava-and-boris-the-spider). – Ashish Srivastava Jul 23 '14 at 07:17
  • It's looks suspiciously like you area sticking arbitrary code into a class rather than a block or method. Is that the case? As the compiler points out that is invalid. – Boris the Spider Jul 23 '14 at 07:23
  • actually i have an IP camera which is have an IP address i want to check the camera is alive or not so i already create TCP listener but i want listener is run with some time interval that's mean i have to use a thread bt there is condition from my senior they don't want use any kind of loop to do this so tell what i have to do for achieve this functionality and also listener is always run its mean thread which is never end – Ashish Srivastava Jul 23 '14 at 07:23
  • Right, I'm not sure how that's relevant. The code you posted is invalid, correct the compiler error and it will work. – Boris the Spider Jul 23 '14 at 07:28
  • A syntax error _is a_ compiler error. I will repeat what I said, correct your syntax. – Boris the Spider Jul 23 '14 at 07:39
  • java.lang.ClassFormatError: Duplicate field name&signature in class file demo/Test – Ashish Srivastava Jul 23 '14 at 08:00
  • public class Test implements Runnable { public static void main(String[] args) { // TODO code application logic here Test ts = new Test(); ts.run(); } final Timer timer = new Timer("MyTimer"); timer.schedule(new TimerTask() { @Override public void run() { System.out.println(System.currentTimeMillis()); } }, 0, TimeUnit.SECONDS.toMillis(1)); } – Ashish Srivastava Jul 23 '14 at 08:00