high resolution timer in java

2020-03-04 03:44发布

问题:

I want to simulate TCP in Java.

For that I have multiple threads, like sender and receiver threads for every TCP connection.

My problem is, I want to pause (like Thread.sleep()) threads for microseconds time interval. So that I can simulate flow control, where sender thread will block for microseconds before sending next packet, and at same time CPU can be used by receiving and data processing threads. But I couldn't find any methods which perform sleep() or wait() for microsecond or nanosecond resolution. How can I block (pause) threads in Java with micro or nanosecond resolution?

I found System.nanoTime() method, but there no methods for blocking threads for specified micro or nano seconds. If there any such methods, then please let me know. System.nanoTime() just gives relative time interval in nanoseconds.

I can use System.nanoTime() to perform nanosecond delay in threads using busy-loop, but that will waste CPU, which could have been used for receiving data thread or processing thread.

Another confusing question:

By surfing internet, I found Thread.sleep() or wait() methods blocks for at least specified milliseconds or in multiple of 10ms, whichever is less, without thread interrupt, in Windows System. But when I run sample examples, I found very different results. Like threads are sleeping less than specified milliseconds. Some threads are giving me 100 microsecond sleep. Is it error in time measured? Is not System.nanoTime() that much accurate? See below example where I am getting very different results. Thread priorities are also not giving predicted results.

public class MyClass {
    public static void main(String args []){
        Runnable r = new Runnable() {
            public void run() {
                long s = System.nanoTime();
                //Thread.yield();  // Try for yield, need to check - in how much time high priority thread will be scheduled back after yielding
                try{
                    Thread.sleep(1);
                }catch(Exception e){

                }
                long e = System.nanoTime() - s;
                System.out.println(Thread.currentThread().getName()+e);
            }
        };

        Thread t1 = new Thread(r, "Thread T1: ");
        t1.setPriority(Thread.MAX_PRIORITY);
        t1.start();

        Thread t2 = new Thread(r, "Thread T2: ");
        t2.setPriority(Thread.MIN_PRIORITY);
        t2.start();

        Thread t3 = new Thread(r, "Thread T3: ");
        t3.setPriority(Thread.NORM_PRIORITY);
        t3.start();

        Thread t4 = new Thread(r, "Thread T4: ");
        t4.setPriority(Thread.MAX_PRIORITY);
        t4.start();

        long s = System.nanoTime();
        try{
            Thread.sleep(1);
        }catch(Exception e){

        }
        long e = System.nanoTime() - s;
        System.out.println("Main: "+e);
    }
}

In my System with Intel Core i5, 2.53 GHz, I am getting outputs similar like below in multiple runs. *New-line in below output is not printed in this post, I have copied output from console, but its giving me new-line in my my console, that's not problem.

Thread T1: 736682 Thread T3: 700212 Thread T2: 478559 Main: 548257 Thread T4: 458299

Second run -

Thread T3: 27555 Thread T2: 139799 Thread T1: 152361 Main: 93199 Thread T4: 29986

Third run -

Thread T4: 724525 Thread T2: 1050319 Main: 752486 Thread T1: 941316 Thread T3: 1000883

Fourth run -

Thread T1: 174243 Thread T2: 166543 Thread T3: 1005745 Main: 1023170 Thread T4: 915787

In above runs, I am getting microseconds blocking. :O

Please guide me on this.

Apologize for long post. Thank you for reading whole post.

回答1:

You're at the mercy of the OS thread scheduler, and you can't do much about it. Just because you sleep for a very short time doesn't mean the scheduler will awake your thread as soon as it has finished sleeping. And thread priorities are only a hint, without any guarantee.



回答2:

Note that Thread.sleep(timeout) guarantees that the Thread will sleep for at least timeout ms (subject to the precision of the underlying system), but it might sleep longer.

There is a Thread.sleep(millis, nanos), but the precision is not very good either. As @TimBender points out below, in OpenJDK 6-b14, it even implements this by rounding and calling Thread.sleep(millis). So, it's fairly safe to say that you can't rely on it to sleep for an exact interval in any Java implementation.



回答3:

Try this:

Thread.sleep(0, 250); // sleep 250 nanoseconds


回答4:

I believe that what you want to use is Condition.awaitNanos, however I can not find any hard evidence to substantiate that this will return with high precision close to the requested time.

Alternatively, you can pass an "awaitNanos" time which is slightly less than the total time desired and then "live wait" in a loop until the total time has passed.