sleep和wait的区别,以及源码解读

首先要明确,wait是Object类的方法,也就是说,所有的对象都有wait方法,而且都是Object中的wait方法因为wait方法被标为final无法被重写,源码如下:

[java]  view plain  copy
  1. public final native void wait(long timeout) throws InterruptedException;  

    native关键字修饰,表示这个方法使用其他语言实现,又由java由C编写可得,这个方法做了很可能是C与操作系统级别的交互。抛出InterruptedException,表示线程可能由已经终止的风险。

    Object提供了几个wait方法:

                    

    最终都调用了我上面贴了源码的那个方法。这里wait由两个参数的方法需要解释一下,一个long类型参数表示的就是线程等待时间,第二个int类型参数nanos表示纳秒,1毫秒=1000微秒=1000000纳秒。当参数nanos超过500000时,等待的毫秒值也就是timeout++,源码如下:

[java]  view plain  copy
  1. public final void wait(long timeout, int nanos) throws InterruptedException {  
  2.        if (timeout < 0) {  
  3.            throw new IllegalArgumentException("timeout value is negative");  
  4.        }  
  5.   
  6.        if (nanos < 0 || nanos > 999999) {  
  7.            throw new IllegalArgumentException(  
  8.                                "nanosecond timeout value out of range");  
  9.        }  
  10.   
  11.        if (nanos >= 500000 || (nanos != 0 && timeout == 0)) {  
  12.            timeout++;  
  13.        }  
  14.   
  15.        wait(timeout);  
  16.    }  

    说是为wait方法提供了更加精准的时间控制,但是这个也略敷衍了吧。处理方法明白说 - 就是大于半毫秒的+1毫秒,小于半毫秒的直接舍弃。

    说完wait的源码,看一下停止wait的方法,notify和notifyAll。

    与wait一样,notify和notifyAll也是Object提供的方法,也是native方法。

    两者的区别就在这个All上,下面详细介绍一下:

    1.notify :随机 (据说与线程优先级有关) 唤醒一个登记集中的等待线程,该线程将从等待集中移除,重新加入对CPU时间片的竞争当中。

    2.notifyAll:唤起所有等待集中的等待线程,所有都加入对CPU时间片的争夺中,先抢到锁的先执行。

wait和notify和notifyAll的使用场景:

       已知wait有释放同步锁的效果,即当处于synchronized方法中的线程进入wait后,synchronized锁将会自动被释放,其他线程可以申请锁、持有锁,然后进入这个synchronized方法进行运行。

        notify和notifyAll后并不会返回之前持有的锁,而是一起开始竞争锁,谁先竞争到了,谁先执行。


    接下来说一下sleep方法,这个方式是由Thread提供的native方法,与wait一样,抛出了InterruptedException异常:

[java]  view plain  copy
  1. /** 
  2.      * Causes the currently executing thread to sleep (temporarily cease 
  3.      * execution) for the specified number of milliseconds, subject to 
  4.      * the precision and accuracy of system timers and schedulers. The thread 
  5.      * does not lose ownership of any monitors. 
  6.      * 
  7.      * @param  millis 
  8.      *         the length of time to sleep in milliseconds 
  9.      * 
  10.      * @throws  IllegalArgumentException 
  11.      *          if the value of {@code millis} is negative 
  12.      * 
  13.      * @throws  InterruptedException 
  14.      *          if any thread has interrupted the current thread. The 
  15.      *          <i>interrupted status</i> of the current thread is 
  16.      *          cleared when this exception is thrown. 
  17.      */  
  18.     public static native void sleep(long millis) throws InterruptedException;  
  19.   
  20.     /** 
  21.      * Causes the currently executing thread to sleep (temporarily cease 
  22.      * execution) for the specified number of milliseconds plus the specified 
  23.      * number of nanoseconds, subject to the precision and accuracy of system 
  24.      * timers and schedulers. The thread does not lose ownership of any 
  25.      * monitors. 
  26.      * 
  27.      * @param  millis 
  28.      *         the length of time to sleep in milliseconds 
  29.      * 
  30.      * @param  nanos 
  31.      *         {@code 0-999999} additional nanoseconds to sleep 
  32.      * 
  33.      * @throws  IllegalArgumentException 
  34.      *          if the value of {@code millis} is negative, or the value of 
  35.      *          {@code nanos} is not in the range {@code 0-999999} 
  36.      * 
  37.      * @throws  InterruptedException 
  38.      *          if any thread has interrupted the current thread. The 
  39.      *          <i>interrupted status</i> of the current thread is 
  40.      *          cleared when this exception is thrown. 
  41.      */  
  42.     public static void sleep(long millis, int nanos)  
  43.     throws InterruptedException {  
  44.         if (millis < 0) {  
  45.             throw new IllegalArgumentException("timeout value is negative");  
  46.         }  
  47.   
  48.         if (nanos < 0 || nanos > 999999) {  
  49.             throw new IllegalArgumentException(  
  50.                                 "nanosecond timeout value out of range");  
  51.         }  
  52.   
  53.         if (nanos >= 500000 || (nanos != 0 && millis == 0)) {  
  54.             millis++;  
  55.         }  
  56.   
  57.         sleep(millis);  
  58.     }  

PS:双参数的sleep与双参数的wait方法一样,提供了更加精细(然而并没有)的时间控制,上面说了就不重复一遍了。

    sleep与wait,在非多线程运行条件下的情况是一样的,都是当前线程让出执行机会,进入休眠/等待。但是在synchronized中就有一些不一样了:

     1.wait会释放同步锁,让其他线程进入synchronized代码块执行。sleep不会释放锁,其他线程只能等待在synchronized代码块中进入sleep的线程醒后执行完毕才能竞争持有锁。

     2.wait可以被notify/notifyAll等方法唤醒,继续竞争CPU和锁。sleep方法只能等待线程睡眠时间到继续运行。

     wait和notify/notifyAll以及sleep的测试代码:

    待补充

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值