美文网首页程序员
生产者与消费者

生产者与消费者

作者: 树獭非懒 | 来源:发表于2018-06-09 16:16 被阅读28次

    我们来实现这样一个效果

    放入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也就是生产者抛出中断异常。

    相关文章

      网友评论

        本文标题:生产者与消费者

        本文链接:https://www.haomeiwen.com/subject/fnwteftx.html