The difference between Java basic wait and sleep

 4 minutes to read

The difference between Java basic wait and sleep

  1. Sleep is a method in Thread, which is a static method, and wait is a method in Object, which is an instance method.

  2. The main function of sleep is to suspend the execution of the thread for a period of time. When the time is up, it will automatically resume. It does not involve thread communication and will not release the lock, but wait will release the lock and add the wait thread to the waiting queue for the lock. go

  3. The sleep method does not depend on the synchronizer synchronized, but wait needs to depend on the synchronized keyword.

  4. Sleep does not need to be awakened (exit blocking after sleeping), but wait is required (no specified time needs to be interrupted by others).

  5. sleep is generally used for the current thread to sleep, or to suspend the operation in a round-robin manner, and wait is mostly used for communication between multiple threads.

Both sleep and wait need to catch the InterruptedException exception. After the call, the current thread will be suspended and the CPU execution time will be given up, but the difference is that sleep will not release the lock resources of the currently held object. After the time is up, it will continue to execute, and wait will give up all locks and need to notify/notifyAll and then re-acquire the object lock resources before continuing to execute.

Thread.sleep(1000) means that this thread will not participate in the CPU competition in the next 1000 milliseconds. After 1000 milliseconds, another thread may be using the CPU at this time, then the operating system will not reallocate the CPU until The thread is suspended or terminated, even if it happens to be the operating system’s turn to allocate CPU at this time, the current thread is not necessarily the one with the highest total priority, and the CPU may still be preempted by other threads. It is also worth mentioning that the role of Thread.Sleep(0) is to trigger the operating system to immediately re-run a CPU competition. The result of the competition may be that the current thread still gains control of the CPU, or another thread may gain control of the CPU. .

wait(1000) means to release the lock for 1000 milliseconds. If the lock is not occupied by other threads after the time, the lock will be obtained again, and then the wait method ends, and the following code is executed. If the lock is occupied by other threads, wait for other threads to release the lock. . Note that once the timeout time has expired, the wait method can automatically unblock without the need for other threads to execute notify, but if the wait method without timeout time is set, it must wait for other threads to execute notify.

An example of sleep not releasing the lock is as follows:

public class SleepLockTest {
    private final static Object lock = new Object();

    public static void main(String[] args) {
        Stream.of("thread1", "thread2").forEach(x -> new Thread(x) {
            @Override
            public void run() {
                SleepLockTest.testSleep();
            }
        }.start());
    }

    private static void testSleep() {
        synchronized (lock) {

            try {
                System.out.println(Thread.currentThread().getName() + "is running");
                Thread.sleep(5000);
                System.out.println(Thread.currentThread().getName() + "finish");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

The results are as follows:

thread1 is running: 1650637494109
thread1 finish
thread2 is running: 1650637499111
thread2 finish

An example where wait will release the lock is as follows:

public class WaitLockTest {
    private final static Object LOCK = new Object();

    public static void main(String[] args) {
        Stream.of("thread1", "thread2").forEach(x -> new Thread(x) {
            @Override
            public void run() {
                WaitLockTest.testWait();
            }
        }.start());
    }

    private static void testWait() {
        synchronized (LOCK) {

            try {
                System.out.println(Thread.currentThread().getName() + " is running:"+System.currentTimeMillis());
                LOCK.wait();
                System.out.println(Thread.currentThread().getName() + "finish");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

The results are as follows:

thread1 is running: 1650637686502
thread2 is running: 1650637686502

To use wait, you must define a synchronized, while sleep does not need to

The following code wait is not in the synchronized code block

public class WaitNoSync {
    private final static Object LOCK = new Object();

    public static void main(String[] args) {
        new Thread(() -> WaitNoSync.testWait()).start();
        
    }

    private static void testWait() {
        try {
            System.out.println(Thread.currentThread().getName() + " is running:" + System.currentTimeMillis());
            LOCK.wait();
            System.out.println(Thread.currentThread().getName() + "finish");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

The results are as follows:

Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at com.company.thread.WaitNoSync.testWait(WaitNoSync.java:18)
at com.company.thread.WaitNoSync.lambda$main$0(WaitNoSync.java:11)
at java.lang.Thread.run(Thread.java:748)