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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个简单的使用wait()和notify()实现的生产者-消费者模型: ``` java public class ProducerConsumer { private List<Integer> buffer = new ArrayList<>(); private int maxSize = 5; public synchronized void produce() throws InterruptedException { while (buffer.size() == maxSize) { wait(); } int item = new Random().nextInt(); buffer.add(item); System.out.println("Produced: " + item); notify(); } public synchronized void consume() throws InterruptedException { while (buffer.size() == 0) { wait(); } int item = buffer.remove(0); System.out.println("Consumed: " + item); notify(); } } ``` 在上述代码中,`buffer`是一个用来存储生产者生产的数据的缓冲区,`maxSize`是缓冲区的最大大小,`produce()`和`consume()`分别表示生产者和消费者的行为。在`produce()`和`consume()`方法中,使用了`wait()`和`notify()`方法来实现线程的等待和唤醒。 在生产者线程中,如果缓冲区已满,就让线程等待(调用`wait()`方法)。如果缓冲区不满,就生产一个随机数,并且将其加入缓冲区中,然后唤醒等待的消费者线程(调用`notify()`方法)。 在消费者线程中,如果缓冲区为空,就让线程等待(调用`wait()`方法)。如果缓冲区不为空,就从缓冲区中取出一个数据,并且将其打印出来,然后唤醒等待的生产者线程(调用`notify()`方法)。 注意,以上代码仅作为示例,是一个比较简单的实现。在实际生产环境中,可能需要更加完善的实现方式来保证线程安全和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值