Java基础wait和sleep的区别

 阅读大约需要2分钟

Java基础wait和sleep的区别

1、sleep是Thread中的方法,是静态方法,wait是Object中的方法,是实例方法。

2、sleep主要作用使线程暂停执行一段时间,时间一到自动恢复,不涉及线程通讯,不会去释放锁,但是wait会释放这个锁,并把这个wait的线程加入到这个锁的等待队列中去

3、sleep方法不依赖于同步器synchronized,但是wait需要依赖synchronized关键字。

4、sleep不需要被唤醒(休眠之后退出阻塞),但是wait需要(不指定时间需要被别人中断)。

5、sleep一般用于当前线程休眠,或者轮循暂停操作,wait多用于多线程之间的通信。

sleep和wait使用时都需要捕获InterruptedException异常,在调用后都会暂停当前线程,并让出CPU的执行时间,但不同的是sleep不会释放当前持有的对象的锁资源, 到时间后会继续执行,而wait会放弃所有锁并需要notify/notifyAll后重新获取到对象锁资源后才能继续执行。

Thread.sleep(1000) 意思是在未来的1000毫秒内本线程不参与CPU竞争,1000毫秒过去之后,这时候也许另外一个线程正在使用CPU,那么这时候操作系统是不会重新分配CPU的,直到那个线程挂起或结束,即使这个时候恰巧轮到操作系统进行CPU分配,那么当前线程也不一定就是总优先级最高的那个,CPU还是可能被其他线程抢占去。另外值得一提的是Thread.Sleep(0)的作用,就是触发操作系统立刻重新进行一次CPU竞争,竞争的结果也许是当前线程仍然获得CPU控制权,也许会换成别的线程获得CPU控制权。

wait(1000)表示将锁释放1000毫秒,到时间后如果锁没有被其他线程占用,则再次得到锁,然后wait方法结束,执行后面的代码,如果锁被其他线程占用,则等待其他线程释放锁。注意,设置了超时时间的wait方法一旦过了超时时间,并不需要其他线程执行notify也能自动解除阻塞,但是如果没设置超时时间的wait方法必须等待其他线程执行notify。

sleep不会释放锁的例子如下:

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();
            }
        }
    }
}

运行结果如下:

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

wait会释放锁的例子如下:

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();
            }
        }
    }
}

运行结果如下:

thread1 is running:1650637686502
thread2 is running:1650637686502

使用wait必须要定义一个synchronized,而sleep不需要

如下代码wait没有在synchronized代码块内

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();
        }
    }
}

运行结果如下:

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)