生产者与消费者

我们来实现这样一个效果

放入20个苹果和取出20个苹果。生产者每次向篮子里放五个苹果,消费者依次取出篮子里的苹果。取出五个苹果后,生产者才能继续往篮子里放。

一、先创建生产者和消费者

1.创建生产者

新建一个生产者继承Thread,目的是向篮子里面放苹果(run方法里面)

class Productor extends Thread
{
	private Basket basket=null;
	public Productor(Basket basket)
	{
		super();
		this.basket=basket;
	}
	public void run()
	{
		basket.pushApple();//向篮子里面放苹果
	}
}
2.创建消费者

新建一个消费者继承Thread,目的是从篮子里取苹果

class Consumer extends Thread
{
	private Basket basket=null;
	public Consumer(Basket basket)
	{
		super();
		this.basket=basket;
	}
	public void run()
	{
		basket.popApple();//从篮子里面取苹果
	}
}

二、实现放苹果和取苹果方法

1.创建篮子类和苹果类

放苹果和取苹果都需要操作篮子和苹果这两个对象,所以我们先创建篮子和苹果类

苹果类很简单,就是一个简单的javaBean。包含苹果的id属性。

class Apple{
	private int id;
	Apple(int id)
	{
		this.id=id;
	}
	public String toString()
	{
		return "苹果"+id;
	}
}

篮子类稍微有点复杂,主要目的就是实现放苹果和取苹果的逻辑

先用一个集合(这里用的是链表集合)存放苹果,用链表集合有个好处,既可以实现先放入的先拿出来,又可以实现先放入的后拿出来。

然后用两个循环分别实现放入20个苹果和取出20个苹果

class Basket{
	private LinkedList<Apple> basket=new LinkedList<Apple>();
	public synchronized void pushApple()
	{
		for(int i=1;i<=20;i++)
		{
			Apple apple=new Apple(i);
			push(apple);
		}
	}
	public synchronized void popApple()
	{
		for(int i=1;i<=20;i++)
		{
			pop();
		}
	}
	public void push(Apple apple)
	{
	...
	}
	private void pop()
	{
	...
	}
}
2.实现生产者放苹果和消费者取苹果

在(1)中可以看到,放苹果pushApple()方法和取苹果popApple中加入了synchronized,实现了这两者的同步方法。即放的时候不能取,取的时候不能放。

接下来看放苹果和取苹果的逻辑

如果篮子里的苹果数不为5.那么就每隔500ms放入一个苹果。即将苹果对象加入到篮子集合中。

当放入5个苹果后,让这个生产者开始等待并唤醒消费者。

此时消费者出场了,消费者开始消费苹果,每隔500ms取出一个。当全部取出时,消费者开始等待并唤醒生产者。

这样一直循环下去,直到放20个苹果和取20个苹果完成后,结束任务。

public void push(Apple apple)
	{
		if(basket.size()==5)
		{
			try{
				wait();
			}catch(InterruptedException e)
			{
			    System.out.println("放入苹果异常"+Thread.currentThread().isInterrupted());
			}
		}
		try{
			Thread.sleep(500);
		}catch(InterruptedException e)
		{
			System.out.println("放入苹果异常"+Thread.currentThread().isInterrupted());
		}
		basket.addFirst(apple);
		System.out.println("存放"+apple.toString());
		notifyAll();
	}
	private void pop()
	{
		if(basket.size()==0)
		{
			try{
				wait();
			}catch(InterruptedException e)
			{
				e.printStackTrace();
			}
		}
		try{
			Thread.sleep(500);
		}catch(InterruptedException e)
		{
			e.printStackTrace();
		}
		Apple apple=basket.removeFirst();
		System.out.println("吃掉"+apple.toString());
		notifyAll();
	}

三、测试

创建生产者和消费者对象,并开始生产和消费

public class ProductConsumerDemo {
	public static void main(String[] args) throws InterruptedException
	{
		Basket basket=new Basket();
		Productor productor=new Productor(basket);
		Consumer consumer=new Consumer(basket);
		productor.start();		
		consumer.start();

	}
}

运行结果:


四、知识拓展

上面代码中在实现wait()方法中会捕捉InterruptedException异常,那么什么情况下会抛出这个异常呢?

这个异常是中断异常,调用线程的interrupt()方法就会抛出这个异常。

比如下面

Thread.sleep(10000);
productor.interrupt();

这个就可以实现10秒后让product也就是生产者抛出中断异常。






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值