一、概述
- wait JVM会把该线程放到等待池中,等待其他线程唤醒该线程,执行该方法的线程对象,释放同步锁。
- notify 执行该方法的线程唤醒在等待池中等待的任意一个线程。
- notifyAll 把线程转到锁池中等待,执行该方法的线程唤醒在等待池中等待的所有线程。
- 执行notify或notifyAll时必须先抢到锁,也就是在synchronized里面
- 上述方法只能被同步监听锁对象来调用,这也是为啥wait() 和 notify()方法都在 Object 对象中。
- 因为同步监听锁可以是任意对象,只不过必须是需要同步线程的共同对象即可,否则别的对象调用会报错:java.lang.IllegalMonitorStateException。
二、已生产一个数据消费一个数据,生产一个数据消费一个数据为例
public class Thread10 {
private Integer index = 0;
private volatile boolean isProducer = false;
private Object LOCK = new Object();
public static void main(String[] args) throws Exception {
final Thread10 t9 = new Thread10();
// 生产者线程
new Thread(new Runnable() {
public void run() {
while (true) {
t9.producer();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
// 消费者线程
new Thread(new Runnable() {
public void run() {
while (true) {
t9.comsumer();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
public void producer() {
synchronized (LOCK) {
if(isProducer) {
// 已生产 -> 设置为wait -> 等待线程唤醒
System.out.println("producer");
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
// 已被消费,再次生产 -> LOCK.notify 唤醒其中一个正在wait等待的线程
index++;
isProducer = true;
System.out.println("producer: " + index);
LOCK.notify();
}
}
}
public void comsumer() {
synchronized (LOCK) {
if(isProducer) {
// 已生产 -> 消费 -> 唤醒其中一个正在wait等待的线程
isProducer = false;
System.out.println("consumer: " + index);
LOCK.notify();
} else {
// 已消费 -> 设置为wait -> 等待线程唤醒
System.out.println("comsumer");
try {
LOCK.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
producer: 1
consumer: 1
comsumer
producer: 2
producer
consumer: 2
comsumer
producer: 3
consumer: 3
producer: 4
consumer: 4
可以看到:有两个线程,一个生产者线程重复着生成数据,一个消费者线程重复消费数据。他们两个都被LOCK锁同步着。
- 当生产者生产出数据设置isProducer为true,打印:producer: 1,并唤醒消费者线程。
- 当cpu切换到消费者线程时因为isProducer为true,所以消费数据设置isProducer为false,打印:consumer: 1,并唤醒生产这线程。
- 当消费数据之后,cpu还在执行消费者线程,因为isProducer为false,没有未消费数据,打印:consumer。设置线程wait,并释放锁。
- 当cpu切换到生产者线程时因为isProducer为false,没有未消费数据,所以生产数据、设置isProducer为true,打印:producer: 2,并唤醒消费者线程。
- 往复循环
三、当多个生产者和多个消费者的时候会产生一些问题,下次记录。。。