package ProducerAndConsumer;
import java.util.ArrayList;
import java.util.List;
/**
* 1,线程中的wait,notifyAll和notify方法,必须是同一个锁对象才有意义。java的每个对象,维持两个队列,一个是线程就绪队列,一个是
* 线程阻塞队列。
* 2,调用对象的wait方法,则该线程被置入阻塞队列(释放对象锁),停止执行。
* 3,调用对象的notify方法,则会随机唤醒该对象阻塞队列中的一个线程,使其进入就绪队列,可以继续往下执行。notifyAll是唤醒该对象阻塞队列的所有线程。
* 4,因此,wait,notifyAll和notify都必须在获得同步锁之后才能使用,换而言之,必须在synchronized 代码快或者方法中使用。否则报IllegalMonitorStateException
* 5,参考链接:https://www.cnblogs.com/qlqwjy/p/10115756.html,感谢作者!
*/
public class WaitNotifyTest {
/**
* 下面的的代码是消费者生产者的例子,使用一个list存储“产品”。
* 生产者和消费者线程必须持有相同的对象锁,下面的例子是以list作为锁,当然也可以用其他对象,只要是同一对象即可。
*/
public static void main(String[] args) throws Exception {
final List<String> list=new ArrayList<>();
/**
* 1,消费者1线程和消费者2线程的代码逻辑是相同的。
* 2,同步代码快中,首先是一个死循环,保证线程不能执行完代码之后就结束。如果list为空,则进入等待。否则消费掉一个“产品”(remove方法),通知其他线程该生产的生产,
* 该消费的消费。
* 3, while(list.size()==0){} 为什么是使用while而不使用if呢?如果使用if并且有两个消费者,两个线程开始执行时,第一次list为空,两个线程都进入等待状态,
* 当生产者生产一个产品通知两个消费者线程消费时,两个线程执行wait之后的代码,不会再去判断list是否为空,所以当一个线程消费掉产品后(remove方法),另一个线程
* 再去消费产品(remove方法),会报数组越界异常。
*/
Thread consumer1=new Thread(()-> {
synchronized (list) {
while(true){
while(list.size()==0){
try {
System.out.println(Thread.currentThread().getName()+"等待中");
list.wait();
} catch (InterruptedException e) {
}
}
System.out.println(Thread.currentThread().getName()+"消费了一个产品");
list.remove(0);
list.notifyAll();
}
}
},"消费者1");
Thread consumer2=new Thread(()->{
synchronized (list) {
while(true){
while(list.size()==0){
try {
System.out.println(Thread.currentThread().getName()+"等待中");
list.wait();
} catch (InterruptedException e) {
}
}
System.out.println(Thread.currentThread().getName()+"消费了一个产品");
list.remove(0);
list.notifyAll();
}
}
},"消费者2");
/**
* 生产者线程,如果数组为空,则生产产品(add方法),否则唤醒其他线程进行消费,自己进入等待状态。直到其他线程消费之后发唤醒通知。
*/
Thread producer1=new Thread(()->{
synchronized (list) {
for (int i = 0; i < 10; i++) {
if(list.isEmpty()){
System.out.println(Thread.currentThread().getName()+"生产了"+i+"号产品");
list.add(i+"号产品");
}else{
try {
list.notifyAll();
list.wait();
} catch (InterruptedException e) {
}
}
}
}
},"生产者1");
producer1.start();
Thread.sleep(100);
consumer1.start();
consumer2.start();
}
}
运行结果:
生产者1生产了0号产品
消费者2消费了一个产品
消费者2等待中
生产者1生产了2号产品
消费者2消费了一个产品
消费者2等待中
生产者1生产了4号产品
消费者2消费了一个产品
消费者2等待中
生产者1生产了6号产品
消费者2消费了一个产品
消费者2等待中
生产者1生产了8号产品
消费者2消费了一个产品
消费者2等待中
消费者1等待中