程序员

生产者与消费者

2018-06-09  本文已影响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也就是生产者抛出中断异常。

上一篇 下一篇

猜你喜欢

热点阅读