0

I tried this :

for(int i =0; i<10; i++)
{
    long t1 = System.nanoTime();
    try{Thread.sleep(1000);}catch(Exception e){}
    double time = (System.nanoTime() - t1)/1000000;
    System.out.println(i+") "+time);
}

And the output of this is :

0) 987.0
1) 999.0
2) 999.0
3) 999.0
4) 999.0
5) 1000.0
6) 999.0
7) 997.0
8) 999.0
9) 999.0

As it is apparent, Thread.sleep() is not exactly accurate, as it slept for 1000 ms only 1 time in 10 tries.

But I thought that it would take more time than 1000 ms, as it would need some time to calculate the value of t1 and time. Any specific reason why it sleeps for less time, and not more than what is specified? (My computer is certainly not a mega-super-computer, gifted by aliens, that it would calculate the value of t1 and time in negative time ! :P )

Also, how can I sleep a thread for exactly 1000 ms?

dryairship
  • 6,022
  • 4
  • 28
  • 54
  • 4
    As the docs stated: Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, **subject to the precision and accuracy** of system timers and schedulers. – PeterMmm Jan 09 '16 at 12:21
  • 5
    You can't, so better rethink your plans. – Kayaman Jan 09 '16 at 12:22
  • The trailing `.0` comes simply from the `toString()` method for `Double`: https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html#toString(double) – PeterMmm Jan 09 '16 at 12:28
  • Either use external hardware or if you trust the accuracy of `System.nanoTime()` sleep for 98% of the time you want to wait and keep doing this with the remaining time you have left until you are within a degree of accuracy you deem acceptable for your needs. Unfortunately, this won't help you much for sub-millisecond degrees of accuracy. Alternatively, don't sleep at all and thrash the CPU at 100% doing a `while (System.nanoTime() < t1 + waitTime) {};` – flungo Jan 09 '16 at 12:29
  • @PeterMmm I never called that! – dryairship Jan 09 '16 at 12:31
  • 1
    Since `System.nanoTime()` returns a long the division `(System.nanoTime() - t1)/1000000` is a long division giving a long result. Assigning the result to a double variable does not restore the fractional part. – Thomas Kläger Jan 09 '16 at 12:36
  • 1
    @PriydarshiSingh, you call `toString()` implicitly when you concatenate a string with a double. And as Thomans mentioned, you never actually use floating-point division because it only gets converted to double at the last moment before assignment. Try `(System.nanoTime() - t1)/1000000.0` instead. – Sergei Tachenov Jan 09 '16 at 12:43
  • @SergeyTachenov This does not occur when I try : `double d = 32.323; System.out.println("d = "+d);` – dryairship Jan 09 '16 at 12:46
  • @PriydarshiSingh, in this case you assign a double literal to a double variable. Then you call `toString()` and of course it works. In the first case you assign a `long` value (computed from the RHS expression) to a double, thus truncating the fractional part. Then you call `toString()` and of course it prints the fractional part equal to zero. Read some literature about how Java expressions are evaluated, maybe even the JLS. – Sergei Tachenov Jan 09 '16 at 12:49
  • Possible duplicate of [How long it takes for one second in Java? Measure latency time in Java](http://stackoverflow.com/questions/21193657/how-long-it-takes-for-one-second-in-java-measure-latency-time-in-java) – Svetlin Zarev Jan 09 '16 at 13:25
  • May I ask why do you need such an accurate sleep? Even already running code can be preempted and delayed for an unspecified time by the os. Are you concerned about cumulative timing errors after a long time? You can correct those by sleeping for a little longer or shorter, or using periodical callbacks in an executor – Tamas Hegedus Jan 09 '16 at 13:49

2 Answers2

1

From the Java documentation of sleep

Causes the currently executing thread to sleep (temporarily cease execution) for the specified number of milliseconds, subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors.

As the documentation says sleep has a dependency with the underlying system, this might not work properly where precision is required.

A good alternative will be ScheduledExecutorService. Below are some code snippets on how to use it:

1. Create ScheduledExecutorService

public static ScheduledExecutorService createScheduledExecutorService(Runnable command){
        ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        scheduledExecutorService.scheduleAtFixedRate(command, 0, 1, TimeUnit.SECONDS);
        return scheduledExecutorService;
    }

Edit: Here, I have hard coded the initial delay with value 0, period with 1 and TimeUnit Seconds. Read more about scheduleAtFixedRate.

2. Create your Runnable task

public class Work implements Runnable{

 @Override
 public void run() {
    //Do Some thing here.
 }

}

3. Run it

public class Main {
    public static void main(String[] args) 
    {
        ExecutorServiceFactory.createScheduledExecutorService(new Work());
    }
}
Somnath Musib
  • 3,548
  • 3
  • 34
  • 47
0

Used ScheduledExecutorService . this is good for your program , becuase you are not using any threads .

    ScheduledExecutorService as= Executors.newSingleThreadScheduledExecutor();
    as.scheduleAtFixedRate(new ,i,0,TimeUnit.MINUTES);
Waseem Saeed
  • 85
  • 1
  • 13