我们来实现这样一个效果
放入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 basket=new LinkedList();
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){
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也就是生产者抛出中断异常。
网友评论