sleep和wait的区别

sleep和wait的区别

我们先一个一个看,看完自然就知道他们之间的区别了

sleep

sleep是Thread类里面的native方法,作用是让当前执行的线程休眠指定的毫秒数。

public static native void sleep(long millis) throws InterruptedException;

当参数millis小于0时,抛出异常

java.lang.IllegalArgumentException: timeout value is negative

此休眠的线程可以被中断,并且抛出InterruptedException异常,并且必须捕获InterruptedException异常

    public static void main(String[] args) {
        Thread thread = new Thread(()->{
            System.out.println("我开始休眠");
            try {
                Thread.sleep(2000);
                System.out.println("我睡完了");
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println("我正在睡觉被中断了");
            }
        });
        thread.start();
        thread.interrupt();
    }

输出

我开始休眠
java.lang.InterruptedException: sleep interrupted
	at java.lang.Thread.sleep(Native Method)
	at org.janusgraph.diskstorage.cache.wkwTest.demo1.lambda$main$0(demo1.java:8)
	at java.lang.Thread.run(Thread.java:748)
我正在睡觉被中断了

sleep导致休眠的线程如果持有锁,是不会释放锁的。
sleep有两个带参的重载方法
第一个就是上面的一个参数的
第二个如下:

    public static void sleep(long millis, int nanos)
    throws InterruptedException {
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        sleep(millis);
    }

我现在一直想不通为啥会有个带两个参数的sleep方法,api上说的是让当前线程进入休眠期指定的毫秒数加上指定的纳秒数。第二个参数就是纳秒数,我感觉是jdk在开的一个玩笑,java应该是不支持纳秒级的定时器的,而且从源码中可以看出第二个参数的逻辑是,如果纳秒数大于等于500000或者毫秒数等于0并且纳秒数在0到500000之间的时候休眠的毫秒数加一,反正我是想不出为啥这么弄,我想多休眠一秒,直接多写1到行了还,话搞的这么麻烦。

wait

wait是Object类里面的native方法

public final native void wait(long timeout) throws InterruptedException;

作用也是让当前的线程进行休眠,wait必须在同步块里面使用,因为他是配合notify使用的,叫醒同一个锁上面等待的线程,要是没有同步块的锁对象,鬼知道notify怎么叫,去叫谁。并且wait休眠的时候是会释放锁的。sleep不释放锁,重点记住!

wait如果没有在同步块里面就会报IllegalMonitorStateException异常

        public static void main(String[] args) {
            Object lock = new Object();
            Thread thread = new Thread(()->{
                //synchronized (lock) {
                    System.out.println("我要开始休眠了");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        System.out.println("我的休眠被打断了");
                    }
                //}
            });
            thread.start();
        }

输出:

我要开始休眠了
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at org.janusgraph.diskstorage.cache.wkwTest.demo1.lambda$main$0(demo1.java:10)
	at java.lang.Thread.run(Thread.java:748)

wait也可以被中断。抛出InterruptedException异常,并且必须捕获InterruptedException异常

        public static void main(String[] args) {
            Object lock = new Object();
            Thread thread = new Thread(()->{
                synchronized (lock) {
                    System.out.println("我要开始休眠了");
                    try {
                        lock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        System.out.println("我的休眠被打断了");
                    }
                }
            });
            thread.start();
            thread.interrupt();
        }

输出:

我要开始休眠了
java.lang.InterruptedException
	at java.lang.Object.wait(Native Method)
	at java.lang.Object.wait(Object.java:502)
	at org.janusgraph.diskstorage.cache.wkwTest.demo1.lambda$main$0(demo1.java:10)
	at java.lang.Thread.run(Thread.java:748)
我的休眠被打断了

wait有三个重载方法:
在这里插入图片描述
wait()相当于wait(0),表示如果没有被唤醒,将一直休眠

    public final void wait() throws InterruptedException {
        wait(0);
    }

下面是wait两个参数的实现

    public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos > 0) {
            timeout++;
        }

        wait(timeout);
    }

可以看出来和sleep的两个参数的实现是异曲同工,不同的是wait中只要纳秒数大于0就将休眠的时间加1,和sleep的就是这点儿区别,到底为啥我也不清楚,连这个方法存在的意义是啥都不清楚,同样打个问号。

好了,这里就说完了sleep和wait,至于其中的区别和相同点,相信看完大家就都应该知道了。
最后面试官还喜欢问的一个就是为什么sleep在Thread类中,而wait在Object中?我的理解是:
sleep是线程自己的行为,你把你自己当成线程,你要休眠是你自己的行为,别人又管不住,所以sleep就是我自己的方法。天下之大,我要睡就睡!

wait是用于线程间的通信,不能自己说了算,两个线程之间得找个传话的,谁适合当这个传话的,想来想去,发现Object最适合,相当于只要确定是个对象就有这个传话的功能,所以就把wait放到了Object类里面。比如师妹在洗澡,大师兄和二师兄都想偷看,但是门缝就能一个人看,然后师傅就当起了这个中间人,大师兄正在聚精会神的看,师傅说好了,该二师兄看了。就是这个意思,师傅这个角色当然换成任何一个人都可以,这就是wait在Object方法中的原因。
总的来说就是sleep是自己的行为,当然可以在自己的类里面了,
wait是监视器,和线程没关系,只不过是用于两个线程通信,适合当这个监视器的对象就是Object了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值