Java生产消费者模型介绍和写法

一.模型定义

1.生产者持续生产,直到缓冲区满,阻塞;2.缓冲区不满后,继续生产消费者持续消费,直到缓冲区空,阻塞;3.缓冲区不空后,继续消费生产者可以有多个,消费者也可以有多个

二.几种写法

1.常规写法:

/**
 * @author Seven 消费者线程 可能有多个消费者
 *
 */
public class Consumer extends Thread{

	Repo repo;
	public Consumer(Repo repo) {
		super();
		this.repo = repo;
	}
	
	@Override
	public void run() {
		super.run();
		while(true) {
			repo.remove();
			try {
				Thread.sleep(5000); //凸显生产线程超过额定数量时阻塞
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

}

/**
 * @author Seven 生产者线程
 *
 */
public class Producer extends Thread{
	Repo repo;
	public Producer(Repo repo) {
		super();
		this.repo = repo;
	}



	@Override
	public void run() {
		super.run();
		
		while(true) {
			repo.add();
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
		
	}
}




/**
 * @author Seven 仓库类
 *
 */
public class Repo {

	int capacity = 10; // 仓库最大容量

	List<Integer> repsList = new ArrayList<Integer>(); // 共享数据区

	/**
	 * 同步方法,向共享数据区添加数据,如果当前数据区等于仓库最大容量, 需要让生产线程等待执行
	 * 
	 */
	public synchronized void add() {
		String name = Thread.currentThread().getName();
		if (repsList.size() == 10) {
			// 最大容量,等待
			try {
				System.out.println(name + "添加货物失败" + ",已经超过仓库最大容量了,线程阻塞中,需要等待添加。。。。。");
				wait();
				System.out.println("线程等待后执行》》》》》》》》》》》");
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} else {
				repsList.add(1);
				System.out.println(name + "添加货物成功");
				System.out.println("只要有货物,生产者就唤醒消费线程获取货物《《《");
				notifyAll();// 唤醒在此对象监视器上等待的线程
		
			
		}
	

		
	}

	/**
	 * 同步方法,移除共享数据区第一条数据,如果没有数据,则让其线程等待
	 */
	public synchronized void remove() {
		String name = Thread.currentThread().getName();
		if (repsList.size() == 0) {
			try {
				notifyAll();
				System.out.println(name + "消费货物失败" + ",仓库已经没有货物了,需要生产者生产货物。。。");
				wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} else {
			repsList.remove(0);
			System.out.println(name + "消费货物成功");
		}
	}

}

package com.ts.consumer;

/**
 * @author Seven 测试类
 *
 */
public class TsMain {

	public static void main(String[] args) {
		Repo repo=new Repo();
		Producer p=new Producer(repo);
		p.setName("生产者线程");
		Consumer c1=new Consumer(repo);
		Consumer c2=new Consumer(repo);
		c1.setName("小明消费者");
		p.start();
		c1.start();

	}
}

输出日志:
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
小明消费者消费货物成功
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物成功
只要有货物,生产者就唤醒消费线程获取货物《《《
生产者线程添加货物失败,已经超过仓库最大容量了,线程阻塞中,需要等待添加。。。。。

2.用阻塞队列实现

生产者:

public class Producer extends Thread{

	public Producer(BlockingQueue bq) {
		super();
		this.bq = bq;
	}
	BlockingQueue bq;
	@Override
	public void run() {
		super.run();
		while(true) {
			try {
				System.out.println("生产数据");
				bq.put(1);//put()方法:类似于我们上面的生产者线程,容量达到最大时,自动阻塞。
				Thread.sleep(300);
			} catch (InterruptedException e) {
				System.out.println("生产数据异常");
				e.printStackTrace();
			}
		}
	}


}

消费者:

public class Consumer extends Thread{

	BlockingQueue bq;

	public Consumer(BlockingQueue bq) {
		super();
		this.bq = bq;
	}
	@Override
	public void run() {
		super.run();
		while(true) {
			try {
				System.out.println(getName()+"取出"+bq.take());//take()方法:类似于我们上面的消费者线程,容量为0时,自动阻塞。
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				System.out.println("取出异常");
				e.printStackTrace();
			}
		}
	}
}

测试代码

public class TsMain {

	public static void main(String[] args) {
		BlockingQueue bq=new LinkedBlockingQueue(10);
		Consumer c=new Consumer(bq);
		c.setName("c1");
		Producer p=new Producer(bq);
		Consumer c2=new Consumer(bq);
		c2.setName("c2");
		c.start();
		p.start();
		c2.start();
	}
}

测试打印
生产数据
c1取出1
生产数据
c2取出1
生产数据
生产数据
c1取出1
生产数据
c2取出1
生产数据
生产数据
c1取出1
生产数据
c2取出1
生产数据
生产数据
c1取出1
生产数据
c2取出1
生产数据
生产数据
生产数据
c1取出1
生产数据
c2取出1
生产数据
生产数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值