sleep和wait的区别,以及源码解读 - java - 总结的超好!


wait()


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

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++,

源码如下:

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 >= 500000 || (nanos != 0 && timeout == 0)) {  
           timeout++;  
       }  
  
       wait(timeout);  
   }  

说是为wait方法提供了更加精准的时间控制,但是这个也略敷衍了吧。


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

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

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

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


wait和notify和notifyAll的使用场景:

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

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


InterruptedException 捕捉


Thread.iterrupt()

package cn.edut.com.test;

public class Test_Thread {
	static Object obj = new Object() ;
	
	public static void main(String[] args) throws InterruptedException {
		T t = new T();
		t.start(); 
		Thread.sleep(1000);
		
//		synchronized(obj) {
//			obj.notifyAll();
//		}
		t.interrupt();
	}
	static class T extends Thread {
		@Override
		public void run() {
			synchronized (obj) {
				try {
					long start = System.currentTimeMillis();
					obj.wait(10000);
					long end = System.currentTimeMillis();
					System.out.println("等待了"+(end-start)/1000+"秒");
					
				} catch (InterruptedException e) {
					System.out.println("Interrupted  !!!!");
					e.printStackTrace();
				}
			}
		}
	}
}


在这里插入图片描述


notify / notifyAll


notifyAll

package cn.edut.com.test;

public class Test_Thread {
	static Object obj = new Object() ;
	
	public static void main(String[] args) throws InterruptedException {
		T t = new T();
		t.start(); 
		Thread.sleep(1000);
		
		synchronized(obj) {
			obj.notifyAll();
		}
		//t.interrupt();
	}
	static class T extends Thread {
		@Override
		public void run() {
			synchronized (obj) {
				try {
					long start = System.currentTimeMillis();
					obj.wait(10000);
					long end = System.currentTimeMillis();
					System.out.println("等待了"+(end-start)/1000+"秒");
					
				} catch (InterruptedException e) {
					System.out.println("Interrupted  !!!!");
					e.printStackTrace();
				}
			}
		}
	}
}


在这里插入图片描述


sleep()

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

/** 
     * Causes the currently executing thread to sleep (temporarily cease 
     * execution) for the specified number of milliseconds, subject to 
     * the precision and accuracy of system timers and schedulers. The thread 
     * does not lose ownership of any monitors. 
     * 
     * @param  millis 
     *         the length of time to sleep in milliseconds 
     * 
     * @throws  IllegalArgumentException 
     *          if the value of {@code millis} is negative 
     * 
     * @throws  InterruptedException 
     *          if any thread has interrupted the current thread. The 
     *          <i>interrupted status</i> of the current thread is 
     *          cleared when this exception is thrown. 
     */  
    public static native void sleep(long millis) throws InterruptedException;  
  
    /** 
     * Causes the currently executing thread to sleep (temporarily cease 
     * execution) for the specified number of milliseconds plus the specified 
     * number of nanoseconds, subject to the precision and accuracy of system 
     * timers and schedulers. The thread does not lose ownership of any 
     * monitors. 
     * 
     * @param  millis 
     *         the length of time to sleep in milliseconds 
     * 
     * @param  nanos 
     *         {@code 0-999999} additional nanoseconds to sleep 
     * 
     * @throws  IllegalArgumentException 
     *          if the value of {@code millis} is negative, or the value of 
     *          {@code nanos} is not in the range {@code 0-999999} 
     * 
     * @throws  InterruptedException 
     *          if any thread has interrupted the current thread. The 
     *          <i>interrupted status</i> of the current thread is 
     *          cleared when this exception is thrown. 
     */  
    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);  
    }  

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


InterruptedException 捕捉


Thread.iterrupt()
package cn.edut.com.test;

public class Test_Thread {
	public static void main(String[] args) {
		T t = new T();
		t.start(); 
		//t.notify();//无法用notify唤醒
		t.interrupt();
	}
}

class T extends Thread {
	@Override
	public void run() {
		try {
			sleep(3000);
			System.out.println("没有打断");
		} catch (InterruptedException e) {
			
			System.out.println("这里!!!");
			
			e.printStackTrace();
		}
	}
}

在这里插入图片描述


notifyAll()、notify()


notifyAll()

无法唤醒,该等3秒,还是等了三秒


package cn.edut.com.test;

public class Test_Thread1 {
	public static void main(String[] args) {
		T t = new T();
		t.start();
		synchronized(t ) {
			t.notifyAll();//无法用notify唤醒
		}
		//t.interrupt();
	}
}

class T extends Thread {
	@Override
	public void run() {
		try {
			long start = System.currentTimeMillis();
			sleep(3000);
			long end = System.currentTimeMillis();
			System.out.println("等待:"+ (end - start)/1000 +"秒");
		} catch (InterruptedException e) {
			
			System.out.println("这里!!!");
			
			e.printStackTrace();
		}
	}
}

在这里插入图片描述


对比

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

但是在synchronized中就有一些不一样了

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

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



总结 - ∗ ∗ 细 看 ∗ ∗ \color{#ff0011}{** 细看 **}


方法提供释放锁?备注异常Iterrupted 情况被唤醒情况
waitObject的final方法 (不能被Override) 释 放 \color{#ff0011}{释放} !!需要用synchronized包围InterruptedExceptioniterrupt() 等 待 等 待 时 间 结 束 、 n o t i f y ( ) 、 n o t i f y A l l ( ) 唤 醒 ( 需 要 用 s y n c h r o n i z e d 包 围 ) \color{#ff0011}{等待等待时间结束 、notify()、notifyAll() 唤醒(需要用synchronized包围)} notify()notifyAll()synchronized
sleepThread的静态方法 不 \color{#ff0011}{不} InterruptedExceptioniterrupt() 只 能 等 待 等 待 时 间 结 束 \color{#ff0011}{只能 等待等待时间结束}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

骆言

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值