Java线程_生产者消费者模型

生产者消费者模型

定义

生产者消费者是一个多线程同步问题的经典模型,也是线程通信的经典模型。

线程通信

不同的线程执行不同的任务,如果这些任务有某种关系,各个线程必须要能够通信,从而完成工作。

模型描述

生产者生成一定量的数据放到缓冲区中,然后重复此过程;与此同时,消费者也在缓冲区消耗这些数据。
生产者和消费者之间必须保持同步:
要保证生产者不会在缓冲区满时放入数据,消费者也不会在缓冲区空时消耗数据。不够完善的解决方法容易出现死锁的情况,此时进程都在等待唤醒。在这里插入图片描述

模型分析

  1. 消费者和生产者同时访问该内存,那么肯定通过多线程实现模型。
  2. 采用某种机制保护生产者和消费者之间的同步。
    保证同一资源被多个线程并发访问时的完整性。
    常用的同步方法是采用信号或加锁机制,保证资源在任意时刻至多被一个线程访问。
创建数据类

我们首先创建数据类,来模拟生产者生产和消费者消费的产品。

public class Data {

	int number = 0;
	
}
使用synchronized修饰

多线程并发同一资源,要把它们的方法用synchronized修饰保证它们生产和消费不同时进行。

wait() / notify()方法

wait()方法:执行该方法的对象释放同步锁,JVM把该线程存放到等待池中,等待其他线程唤醒。
notify()方法:唤醒在等待池中的等待的任意一个线程,把线程转移到锁池中。

当生产者生产商品满时,停止执行,放弃锁进入等待,并通知消费者进行消费。
当消费者消费商品完时,停止执行,放弃锁进入等待,并通知生产者进行生产。

设置线程休眠

在生产者线程和消费者线程中,设置线程线程休眠,保证线程间通信的正常进行。

创建线程仓库

在生产者线程和消费者线程中,储存线程。

代码如下所示

创建数据类
public class Data {

	int number = 0;
	
}
生产者线程
public class Producer implements Runnable{

	// 保存数据的仓库
	private List<Data> listData;
	private int MAX = 10;
	
	public Producer(List<Data> listData) {
		this.listData = listData;
	}

	// 生命周期:
	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
			// 同步代码快:synchronized(监视器/锁){  需要同步的代码块..} 
			// 监视器:任何一个对象都可以作为监视器使用
			// 在多线程状态下,所有的线程使用的监视器必须是同一个
			synchronized(listData){
				if(listData.size() < MAX){
					// 休眠
					try {
						Thread.sleep(100);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					// 生产者向仓库添加数据
					listData.add(new Data());
					System.out.println(Thread.currentThread().getName()+":生产产品,剩余产品"+listData.size());
					
					// 唤醒线程
					listData.notify();
				}else{
					//休眠
					try {
						System.out.println("仓库已满!!!");
						// 线程休眠
						listData.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
	}
}

消费者线程
public class Consumer implements Runnable{
	
	private List<Data> listData;
	
	public Consumer(List<Data> listData) {
		this.listData = listData;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while(true){
			// 同步代码快:synchronized(监视器/锁){  需要同步的代码块..} 
			// 监视器:任何一个对象都可以作为监视器使用
			// 在多线程状态下,所有的线程使用的监视器必须是同一个
			synchronized(listData){
				if(listData.size() > 0 ){
					// 休眠
					try {
						Thread.sleep(300);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					listData.remove(0);
					System.out.println(Thread.currentThread().getName()+":消费产品,剩余产品"+listData.size());
					// 唤醒线程
					listData.notify();
				}else{
					try {
						System.out.println("仓库没有产品!!");
						// 线程休眠
						listData.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
	}
}
管理者

管理者运行Java主函数

import java.util.ArrayList;
import java.util.List;

public class Manager {

	public static void main(String[] args) {
		// 创建仓库对象
		List <Data> listData = new ArrayList <Data>();
		// 生产者
		Producer producer = new Producer(listData);
		// 消费者
		Consumer consumer = new Consumer(listData);
		// 启动线程
		new Thread(producer,"生产者1:").start();
		new Thread(producer,"生产者2:").start();
		new Thread(consumer,"消费者:").start();
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值