生产者/消费者模型

生产者消费者模型是多线程同步的解决案例之一。生产者用于生产数据存放至缓冲区,也即仓库,而消费者用于消耗仓库中的数据,保证仓库的容量。
在生产者和消费者模型中,我们使用wait()和notify()方法控制生产者和消费者的生产与消费。当仓库已满时,控制生产者不再进行生产,当仓库已空,控制消费者不再进行消费。
在这里,我们需要注意的是wait()和notify()的使用方法。在一个线程中使用wait()方法使线程阻塞后,只能在另一个线程中调用notify()方法唤醒线程,当存在多个线程同时被阻塞,notify()只唤醒优先级最高的被阻塞线程,使用notifyAll()可唤醒全部线程。
为保证线程操作数据的安全,在使用wait()和notify()时要对线程进行同步。

我们以生产小球为例,生产者负责生产小球,消费者负责消耗小球,设置仓库容量为20。

小球

public class Ball {
	
	int x,y;
	Graphics g;
	
	public Ball(int x,int y) {
		this.x=x;
		this.y=y;
	}
	
	public void DrawMe(Graphics g) {
		this.g=g;
		g.fillOval(x, y,50,50);
	}

}

生产者线程

public class ProductionThread extends Thread{
	
	int capacity;
	Graphics g;
	ArrayList<Ball> balls = new ArrayList();
	
	public ProductionThread(int capacity,ArrayList<Ball> balls,Graphics g) {
		this.capacity=capacity;
		this.g=g;
		this.balls=balls;
	}
	
	public void run() {
		while(true){
			
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			synchronized(balls) {
			g.setColor(Color.black);
			g.fillRect(0, 0, 800, 800);
			g.setColor(Color.red);
			Random r = new Random();
			int x=r.nextInt(800);
			int y = r.nextInt(800);
			//System.out.println("x="+x+" y="+y);
			Ball newball = new Ball(x,y);
			balls.add(newball);
			
			for(int j = 0;j<balls.size();j++) {
				Ball ball = balls.get(j);
				ball.DrawMe(g);
			}
			
			System.out.println("生产 一个球,库存:"+balls.size());
			
			if(balls.size()>=capacity) {
				try {
					balls.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}else {
				balls.notify();
			}
		}
		}
	}
	
	
}

消费者线程

public class ConsumptionThread extends Thread{
	int capacity;
	Graphics g;
	int i=0;
	ArrayList<Ball> balls = new ArrayList();
	
	public ConsumptionThread(int capacity,ArrayList<Ball> balls,Graphics g) {
		this.capacity=capacity;
		this.g=g;
		this.balls=balls;
	}
	
	public void run() {
		while(true) {
			try {
				Thread.sleep(150);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			synchronized(balls) {
				if(balls.size()>0) {
				balls.remove(balls.size()-1);
				System.out.println("消费一个球,库存="+balls.size());
				}
			if(balls.size()==0) {
				try {
					balls.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}else{
				balls.notify();
			}
			}
		}
		
	}

}

控制小球对象

public class PC{
	
	public static void main(String[] args) {
		PC pc = new PC();
		pc.init();
	}
	
	public void init() {
		JFrame jf = new JFrame();
		jf.setTitle("画图");
		jf.setSize(new Dimension(800,800));
		jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		
		jf.setVisible(true);
		
		ArrayList<Ball> balls = new ArrayList();
		int Capacity=20;
		int stock;
		
		Graphics g = jf.getGraphics();
		
		ProductionThread pt = new ProductionThread(Capacity,balls,g); 
		pt.start();
		ConsumptionThread ct = new ConsumptionThread(Capacity,balls,g);
		ct.start();
	}

}

部分输出结果如下:

生产 一个球,库存:1
消费一个球,库存=0
生产 一个球,库存:1
生产 一个球,库存:2
消费一个球,库存=1
生产 一个球,库存:2
消费一个球,库存=1
生产 一个球,库存:2
生产 一个球,库存:3
消费一个球,库存=2
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值