在多线程中什么是等待通知机制?
生活总最常见的例子就是上菜系统
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNvwVZ2x2bzNXak9CX90TQNNkRrFlQKBTSvwFbslmZvwFMwQzLcVmepNHdu9mZvwFVywUNMZTY18CX052bm9CX0EERNdXQE5UMNpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2LcRHelR3LcJzLctmch1mclRXY39DMwMjMzYTMyETOyUDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
1:方法wait()方法作用就是使当前执行代码的线程进行等待,该方法是object类的方法,会使当前线程释放锁。该方法只能在同步方法或则同步块中调用wait()方法。
2:notify()方法也要在同步方法或则同步块中调用,该方法用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则有线程规划器随机挑选一个呈wait状态的线程,对其发出通知notify,并使它等待获取该对象的对象锁。在执行notify()方法后,当前线程不会马上释放对象锁,呈wait状态的想爱你成也不会马上获得该对象锁,要等待执行notify()方法的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁,而wait状态所有的线程才可以获取该对象锁。
public class MyList {
private static List list = new ArrayList();
public static void add() {
list.add("anyString");
}
public static int size() {
return list.size();
}
}
public class ThreadA extends Thread {
private Object lock;
public ThreadA(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
try {
synchronized (lock) {
if (MyList.size() != 5) {
System.out.println("wait begin "
+ System.currentTimeMillis());
lock.wait();
System.out.println("wait end "
+ System.currentTimeMillis());
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadB extends Thread {
private Object lock;
public ThreadB(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
try {
synchronized (lock) {
for (int i = 0; i < 10; i++) {
MyList.add();
if (MyList.size() == 5) {
lock.notify();
System.out.println("已发出通知!");
}
System.out.println("添加了" + (i + 1) + "个元素!");
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
try {
Object lock = new Object();
ThreadA a = new ThreadA(lock);
a.start();
Thread.sleep(50);
ThreadB b = new ThreadB(lock);
b.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
下面证明wait()方法释放锁 notify()锁不释放
public class Service {
public void testMethod(Object lock) {
try {
synchronized (lock) {
System.out.println("begin wait()");
lock.wait();
System.out.println(" end wait()");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
A B 两个线程同时访问testMethod()方法,但是A进去后释放了锁,导致B也进来,所以打印两次。
public class Service {
public void testMethod(Object lock) {
try {
synchronized (lock) {
System.out.println("testMethod() begin wait() ThreadName="
+ Thread.currentThread().getName());
lock.wait();
System.out.println("testMethod() end wait() ThreadName="
+ Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void synNotifyMethod(Object lock) {
try {
synchronized (lock) {
System.out.println("synNotifyMethod() begin notify() ThreadName="
+ Thread.currentThread().getName() + " time="
+ System.currentTimeMillis());
lock.notify();
Thread.sleep(5000);
System.out.println("synNotifyMethod() end notify() ThreadName="
+ Thread.currentThread().getName() + " time="
+ System.currentTimeMillis());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadA extends Thread {
private Object lock;
public ThreadA(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
Service service = new Service();
service.testMethod(lock);
}
}
public class synNotifyMethodThread extends Thread {
private Object lock;
public synNotifyMethodThread(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
Service service = new Service();
service.synNotifyMethod(lock);
}
}
public class NotifyThread extends Thread {
private Object lock;
public NotifyThread(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
Service service = new Service();
service.synNotifyMethod(lock);
}
}
public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
ThreadA a = new ThreadA(lock);
a.start();
NotifyThread notifyThread = new NotifyThread(lock);
notifyThread.start();
synNotifyMethodThread c = new synNotifyMethodThread(lock);
c.start();
}
A线程调用wait()方法释放对象锁,NotifyThread线程唤醒,但是得走完同步方法所以睡眠5s,在这期间不会释放对象锁,
5s过后,释放锁了,A线程再执行完wait()方法后面剩下的代码,这个时候synNotifyMethodThread线程才能进入synNotifyMethod()方法执行。
调用notify()方法一次随机只通知一个线程进行唤醒。
public class Service {
public void testMethod(Object lock) {
try {
synchronized (lock) {
System.out.println("begin wait() ThreadName="
+ Thread.currentThread().getName());
lock.wait();
System.out.println(" end wait() ThreadName="
+ Thread.currentThread().getName());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class NotifyThread extends Thread {
private Object lock;
public NotifyThread(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
lock.notify();
}
}
}
只唤醒了0线程。
修改如下代码
public class NotifyThread extends Thread {
private Object lock;
public NotifyThread(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
lock.notify();
lock.notify();
lock.notify();
lock.notify();
lock.notify();
lock.notify();
lock.notify();
lock.notify();
lock.notify();
}
}
}
都唤醒
也可以改成lock.notifyAll();
效果是一样的,唤醒所有的线程。