- wait方法
- wait()和join()的区别
- wait()和sleep()的区别
- notify()和notifyAll()
- 实例
wait()和notify()方法都是Object类中的方法。由于每个类都会继承Object类,所以每个对象中都会包含这些方法。
wait方法
wait() 是让线程等待一段时间,死等。对应到线程的状态就是WAITING。
wait(long) 是让线程等待一段时间,指定的时间到了就不等了,过时不候。对应到线程的状态就是TIMED_WAITING。
wait()和join()的区别
之前介绍过一个join()方法,这个方法也是让线程等待。不同的是:
join()方法是Thread类中的方法。join()是让调用方去等,wait()是让执行方去等。
比如我爸妈让我去买包子,他们必须要等我买回来了才能吃,这个过程就是join(),到了包子铺老板的包子还没出锅,相当于我在等待某些资源,相当于notify()。
wait()和sleep()的区别
本质上来说都是让线程阻塞等待,但是两个方法没啥关系。
①wait()是Object类中定义的方法,sleep是Thread类中定义的方法。
②wait()必须要和synchronized搭配使用,调用之后会释放锁,sleep()只是让线程进入休眠,和锁无关。
notify()和notifyAll()
notify() 方法是唤醒线程,只唤醒一个线程,并直接参与锁竞争;
notifyAll() 一次性唤醒所有的线程,线程共同去参与锁竞争。
比如去包子铺买包子,大家都在等待。包子做好之后老板指定某一个人来买,相当于notify();没指定人相当于大家都可以买,此时就是notifyAll()。
实例
public class Demo03_Wait_Notify {
private static Object locker = new Object();
public static void main(String[] args) {
// 买包子线程
Thread t1 = new Thread(() -> {
while (true) {
System.out.println(Thread.currentThread().getName() + " wait 之前");
try {
// 等待资源,线程会被阻塞
locker.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " wait 之后");
System.out.println("=============================");
}
}, "t1");
// 启动线程
t1.start();
// 包子铺老板线程
Thread t2 = new Thread(() -> {
while (true) {
System.out.println(Thread.currentThread().getName() + " notify 之前");
// 唤醒资源
locker.notify();
System.out.println(Thread.currentThread().getName() + " notify 之后");
// 等待一会
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t2");
// 启动线程
t2.start();
}
}
上面的代码在运行时会报下面的异常:非法的监视器状态异常,所以需要将wait()和notify要用synchronized包裹,确保wait和notify是同一个锁对象。
public class Demo03_Wait_Notify {
private static Object locker = new Object();
public static void main(String[] args) {
// 买包子线程
Thread t1 = new Thread(() -> {
while (true) {
System.out.println(Thread.currentThread().getName() + " wait 之前");
try {
// 等待资源,线程会被阻塞
synchronized (locker) {
locker.wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " wait 之后");
System.out.println("=============================");
}
}, "t1");
// 启动线程
t1.start();
// 包子铺老板线程
Thread t2 = new Thread(() -> {
while (true) {
System.out.println(Thread.currentThread().getName() + " notify 之前");
// 唤醒时也使用同一个锁对象
synchronized (locker) {
locker.notify();
}
System.out.println(Thread.currentThread().getName() + " notify 之后");
// 等待一会
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "t2");
// 启动线程
t2.start();
}
}
从执行结果可以看出wait()和notify()被调用后,当前线程都会释放锁资源。
继续加油~