美文网首页
sleep()方法和wait()方法的区别

sleep()方法和wait()方法的区别

作者: herohua | 来源:发表于2020-01-13 20:25 被阅读0次

JDK官方文档定义:

Thread的sleep方法.png Object的wait方法.png

区别可以总结为如下四点:

1. sleep方法是Thread的方法,而wait方法试试Object的方法

2. sleep不会释放对象锁,而wait方法会释放对象锁并且加入到对象锁的等待队列

定义方法m3

public static void m3() {
    synchronized (LOCK) {
        System.out.println(Thread.currentThread().getName() + " enter");
        try {
            // sleep方法不会释放锁
            //Thread.sleep(10_000);

            // wait方法会释放锁
            LOCK.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

主程序新建两个线程T1、T2运行m3方法

public static void main(String[] args) {

    Stream.of("T1", "T2").forEach(name -> {
        new Thread(() -> {
            m3();
        }, name).start();
    });
}

如调用sleep方法,则在输出"T1 enter"后10秒后再输出"T2 enter",因为线程T1sleep后还会拥有Monitor,不会释放,只有当T1恢复后执行完毕释放Monitor,线程T2才会获得Monitor才会开始执行;
如调用wait方法,则在输出"T1 enter"后会立即输出"T2 enter",因为线程T1wait后会立即释放Monitor,线程T2获得Monitor,继续执行。

3. 使用sleep方法不需要监控锁(synchronized),但使用wait方法需要

先定义两个方法,m1方法调用sleep()方法,m2方法调用wait()方法

public static void m1() {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
public static void m2() {
    try {
        // no synchronized (LOCK) -> IllegalMonitorStateException
        LOCK.wait(1000);
        System.out.println("m2 end...");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

分别调用方法m1、m2,

public static void main(String[] args) {

    m1();

    m2();
}

运行结果:m1方法运行正常,m2方法报IllegalMonitorStateException异常。


image.png

4. sleep方法不需要被唤醒,但wait方法需要

================================================================================

wait方法几点总结

1. 所有的对象都会有一个wait set,用来存放该对象wait方法之后进入block状态的线程
2. 线程被notify之后,不一定会立即执行
3. 线程从wait set被唤醒后顺序不一定是FIFO
4. 线程被唤醒后,必须重新获取锁,但是wait方法之前的代码不再执行,会接着wait方法之后继续执行
public class WaitSet {

    private final static Object LOCK = new Object();

    public static void main(String[] args) {
        IntStream.rangeClosed(1, 10).forEach(
                i -> new Thread(String.valueOf(i)) {
                    @Override
                    public void run() {
                        synchronized (LOCK) {
                            System.out.println(Thread.currentThread().getName() + "start running");
                            try {
                                Optional.of(Thread.currentThread().getName() + " will come to wait set.").ifPresent(System.out::println);
                                LOCK.wait();
                                Optional.of(Thread.currentThread().getName() + " will leave wait set.").ifPresent(System.out::println);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }.start());


        IntStream.rangeClosed(1, 10).forEach(
                i -> {
                    synchronized (LOCK) {
                        LOCK.notify();

                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });
    }
}

执行结果:


测试.png

相关文章

网友评论

      本文标题:sleep()方法和wait()方法的区别

      本文链接:https://www.haomeiwen.com/subject/rzjnactx.html