7

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.

nullptr
  • 3,320
  • 7
  • 35
  • 68
  • There's a sleep method in Thread that can take nanos as a parameter. 'Thread.sleep(int mili, int nano)' - I don't think you can refine to microseconds. – Jiman Oct 29 '12 at 21:00
  • My System is: Intel Core i5, 2.53 GHz, Windows 7 Enterprise OS. – nullptr Oct 29 '12 at 21:01
  • Hi Jiman, isn't Thread.sleep(int mili, int nano) rounds sleep time to millisecond time? – nullptr Oct 29 '12 at 21:05
  • @user1508907 Hard to see what the point iof it would be if it did that, but it is "subject to the precision and accuracy of system timers and schedulers. The thread does not lose ownership of any monitors". – user207421 Oct 29 '12 at 21:18
  • Running your code I get results between 1 and 2 ms for each thread... – assylias Oct 29 '12 at 21:28
  • assylias, I have copied above results from console after running above code, and as per above output I am getting less than 1 ms sleep, right? Is clock running fast in my system? – nullptr Oct 29 '12 at 21:33
  • The answer to this question is here http://www.rationaljava.com/2015/10/measuring-microsecond-in-java.html in this post that discusses busy waiting – Dan Oct 28 '15 at 16:06
  • I've posted a very similar answer some time ago, please have a look to this http://stackoverflow.com/questions/20241426/java-scheduledexecutorservice-bad-precision – snovelli Dec 21 '15 at 11:34

4 Answers4

4

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.

Keppil
  • 45,603
  • 8
  • 97
  • 119
  • 2
    Look at the implementation of the latter method, it just converts everything to the closest millisecond (rounding up). – Tim Bender Oct 29 '12 at 21:04
  • @TimBender: Wow, I knew the precision was bad, but that's even worse than I thought. – Keppil Oct 29 '12 at 21:05
  • @TimBender That is admittedly implementation specific and could change in the future. The exact contract is specified in the javadoc. – assylias Oct 29 '12 at 21:08
  • Keppil, ((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.)) then why I am getting less than 1 ms sleep time in my output. Time measured using System.nanoTime() – nullptr Oct 29 '12 at 21:11
  • Ah, well an alternative is to try to use `Condition.awaitNanos` but I couldn't verify that it would return with any better precision. – Tim Bender Oct 29 '12 at 21:12
  • @user1508907: I can't explain the shorter times with anything other than that it is an unreliable timing method. – Keppil Oct 29 '12 at 21:19
  • @user1508907: There are a few open bugs on Windows and timing, for example [this one](http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6313903). Not sure if that applies to your system. Also you could read https://blogs.oracle.com/dholmes/entry/inside_the_hotspot_vm_clocks for some more ideas. – Keppil Oct 30 '12 at 05:59
3

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.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
0

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.

Tim Bender
  • 20,112
  • 2
  • 49
  • 58
  • 1
    `Condition` is an interface. Which imlpementation do you suggest to use? `ReentrantLock.newCondition` for example uses `LockSupport.parkNanos()` which can return immediately in some conditions. – assylias Oct 29 '12 at 21:17
  • Honestly, using `Condition` at all would be a hack. It would be better to look at the implementation of the `Condition` belonging to `ReentrantLock` and then "borrow" the code pattern for a custom high precision wait. Reading the javadoc, the advantage to `Condition.awaitNanos` is that it will return the leftover nanoseconds so a loop can be used to wait more as needed. Again, I would probably do some borrowing and then innovate with the live wait. – Tim Bender Oct 29 '12 at 21:28
-1

Try this:

Thread.sleep(0, 250); // sleep 250 nanoseconds
Jiman
  • 185
  • 2
  • 13