使用wait和notify实现生产者消费者模式

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 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等待中

 

你可能感兴趣的:(java)