线程的睡眠和等待

sleep是Thread类中提供的用于让线程暂停的方法,可以指定要暂停的时间(毫秒值)

wait则是object中提供的方法,会让当前线程等待,直到被唤醒为止

区别在于线程在阻塞的过程中是否会释放锁?

  • sleep在阻塞的过程中是不释放锁的
  • wait在阻塞的过程中是会释放锁的
  • 首先我们通过代码来看一下Sleep的特点
public class SleepMethod {

	public static void main(String[] args) {
		//创建任务
		PrimeRun primeRun = new PrimeRun();
		//创建线程
		Thread t1 = new Thread(primeRun,"线程A");
		t1.start();
		
		Thread t2 = new Thread(primeRun,"线程B");
		t2.start();

		
	}
}
class PrimeRun implements Runnable{

    private int count = 5;
 
	@Override
	public void run() {
		while(true) {
			synchronized (PrimeThread.class) {
				try {
					System.out.println("线程"+Thread.currentThread().getName()+"获取锁并执行任务");
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("当前是线程"+Thread.currentThread().getName()+"离开锁");
			}
		}
	}
	
}
线程线程A获取锁并执行任务
当前是线程线程A离开锁
线程线程B获取锁并执行任务
当前是线程线程B离开锁
线程线程B获取锁并执行任务
当前是线程线程B离开锁
线程线程B获取锁并执行任务
当前是线程线程B离开锁
线程线程A获取锁并执行任务
当前是线程线程A离开锁

我们可以观察到sleep在线程睡眠的时候是不释放锁的,线程A进去,先输出一个A获取锁并执行任务然后睡眠,然后线程B进不来,要等线程A睡眠结束输出离开锁之后。线程B才能进入

  • 接着我们观察一下wait的特点
public class WaitMethod {

	public static void main(String[] args) {

		// 创建一个唯一锁
		Object object = new Object();
		// 创建线程
		PrimeThread t1 = new PrimeThread(object, "线程A");
		t1.start();

		PrimeThread t2 = new PrimeThread(object, "线程B");
		t2.start();
	}
}
/**
 * wait在进行等待时会释放锁
 */
class PrimeThread extends Thread {

	private int count = 5;//控制一下循环次数 

	private Object object;

	public PrimeThread() {
	}

	public PrimeThread(Object object, String threadName) {
		super.setName(threadName);
		this.object = object;
	}

	@Override
	public void run() {
		while (count > 0) {
			synchronized (object) {
				try {
					--count;
					System.out.println("线程" + Thread.currentThread().getName() + "获取锁并执行任务");
					// 在线程进行等待之前,先去唤醒其他的线程(睡之前先喊个人)
					object.notify();//可以尝试一下注释掉唤醒这一过程(如果注释掉唤醒,再不加等待时间,两个线程就会进入永久等待)
					object.wait();//object作为唯一的锁对象,在这还可以做监视器
					//线程A先进获得锁并执行任务,然后唤醒线程B,线程B进获得锁并执行任务,然后线程B唤醒线程A,自己睡眠,然后线程A输出离开锁。
					//然后新干线再进获得锁并执行任务,唤醒飞跃号..........
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				System.out.println("当前是线程" + Thread.currentThread().getName() + "获取锁");
			}
		}
	}

结果

线程线程A获取锁并执行任务
线程线程B获取锁并执行任务
当前是线程线程A离开锁
线程线程A获取锁并执行任务
当前是线程线程B离开锁
线程线程B获取锁并执行任务
当前是线程线程A离开锁
线程线程A获取锁并执行任务
当前是线程线程B离开锁
线程线程B获取锁并执行任务
当前是线程线程A离开锁
线程线程A获取锁并执行任务
当前是线程线程B离开锁
线程线程B获取锁并执行任务
当前是线程线程A离开锁
线程线程A获取锁并执行任务
当前是线程线程B离开锁
线程线程B获取锁并执行任务
当前是线程线程A离开锁

可以发现,wait在线程等待的时候是会释放锁的,其他的进程可以在被锁住的线程等待期间进入锁并运行线程