生产者和消费者问题

生产者和消费者问题

一、维基百科

  生产者消费者问题(英语:Producer-consumer problem),也称有限缓冲问题(英语:Bounded-buffer problem),是一个多进程同步问题的经典案例。该问题描述了共享固定大小缓冲区的两个进程——即所谓的“生产者”和“消费者”——在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。

  要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有**信号灯法**[1]等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形生产者和消费者问题_第1张图片

二、实战问题

  采用Java 多线程技术,设计实现一个符合生产者和消费者问题的程序。对一个对象(枪膛)进行操作,其最大容量是12颗子弹。生产者线程是一个压入线程, 它不断向枪膛中压入子弹;消费者线程是一个射出线程,它不断从枪膛中射出子弹。

wait()和notify()方法实现

1、枪的实体类

public class Gun {
	//临界资源
	protected final List<Bullet> bullets = new ArrayList<Bullet>();
	
	public int size() {
		return bullets.size();
	}
	public  void pushBullet() {
		bullets.add(new Bullet());
		
	}
	public   void pullBullet() {
		bullets.remove(0);
	}
	protected int count;
	public Gun() {
		int count = 0;
	}
	
	//子弹
	class Bullet{
		
	}
}

2、射出子弹的线程

public class PullBullet implements Runnable {

	private Gun gun;
	
	public PullBullet(Gun gun) {
		super();
		this.gun = gun;
	}

	public void run() {
		try {
			while(true){
				synchronized (gun.bullets) {
					Thread.currentThread().sleep(500);
					while(gun.size() == 0) {
						//弹夹(缓冲区)为空时,该线程等待,进入休眠状态	
						gun.bullets.wait();
					}
					//射出子弹就会唤醒线程
					gun.bullets.notifyAll();
					gun.pullBullet();
					System.out.println("Pull Bullet ..."+gun.size());
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

3、压入子弹线程

public class PushBullet implements Runnable {
	private Gun gun;
	
	public PushBullet(Gun gun) {
		super();
		this.gun = gun;
	}

	public void run() {
		try {
			while(true){
				synchronized (gun.bullets) {
					Thread.currentThread().sleep(500);
					while(gun.size() == 12) {	
							gun.bullets.wait();
					}
					gun.bullets.notifyAll();
					gun.pushBullet();
					System.out.println("Push Bullet ..."+gun.size());
				}
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

4、启动类

	public static void main(String[]args) {
		Gun gun = new Gun();
		Thread push = new Thread(new PushBullet(gun));
		push.setName("push");
		push.start();
		
		Thread pull = new Thread(new PullBullet(gun));
		pull.setName("pull");
		pull.start();
		
	}

5、输出

生产者和消费者问题_第2张图片

你可能感兴趣的:(JAVA高级)