多线程实现生产者消费者案例

Java案例之生产者与消费者

  • 总体概述:
    • 线程生命周期:
  • 案例分析:
  • 结果预览:
  • 具体实现:
  • 原码:

总体概述:

所谓生产者消费者问题,实际上主要是包含了两类线程:

  • 一类是生产者线程用于生产数据
  • 一类是消费者线程用于消费数据

为了解耦生产者和消费者的关系,通常会采用共享的数据区域,就像是一个仓库。

  • 生产者生产数据之后直接放置在共享数据区中,并不需要关心消费者的行为
  • 消费者只需要从共享数据区中去获取数据,并不需要关心生产者的行为

线程生命周期:

多线程实现生产者消费者案例_第1张图片

案例分析:

生产者消费者案例中包含的类:

  • 奶箱类(Box):定义一个成员变量,表示第x瓶奶,提供存储牛奶和获取牛奶的操作
  • 生产者类(Producer):实现Runnable接口,重写run()方法,调用存储牛奶的操作
  • 消费者类(Customer):实现Runnable接口,重写run()方法,调用获取牛奶的操作
  • 测试类(BoxTestt):里面有main方法,main方法中的代码步骤如下:

①创建奶箱对象,这是共享数据区域

②创建生产者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用存储牛奶的操作

③创建消费者对象,把奶箱对象作为构造方法参数传递,因为在这个类中要调用获取牛奶的操作

④创建2个线程对象,分别把生产者对象和消费者对象作为构造方法参数传递

⑤启动线程

结果预览:

多线程实现生产者消费者案例_第2张图片
多线程实现生产者消费者案例_第3张图片

具体实现:

下面是存储牛奶和获取牛奶的操作

  //定义一个成员变量,用来表示第x瓶牛奶
    private  int milk;
    //定义一个成员变量 用于表示牛奶箱子状态
    private boolean state=false;

    //提供存储牛奶和获取牛奶的操作
public synchronized void putMilk(int milk){
if(state){
    try {
        wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
    //如果没有牛奶  则生产牛奶
    this.milk=milk;
    System.out.println("送奶工人将第"+this.milk+"瓶牛奶放入奶箱");

    //生产完毕  修改牛奶箱子状态
        state=true;
    //唤醒其他等待的线程
    notifyAll();

}

    public synchronized  void getMilk() {
    //如果没有牛奶 等待生产
    if(!state){
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //如果有牛奶 就消费牛奶
        System.out.println("用户拿到第"+this.milk+"瓶牛奶");
    //  生产完毕  修改牛奶状态
             state=false;
    //唤醒其他等待的线程
        notifyAll();

    }

原码:

生产者类:

package MultithreadingCase;

public class Producer implements Runnable{
    private final Box b;
    public Producer(Box b) {
        this.b=b;
    }

    @Override
    public void run() {
        //送奶工人将50瓶牛奶放入奶箱
        for(int i=1;i<=50;i++){

            b.putMilk(i);


        }

    }
}

消费者类:

package MultithreadingCase;

public class Customer implements Runnable{
    private final Box b;
    public Customer(Box b) {
        this.b=b;
    }

    @Override
    public void run() {
        while (true){

          b.getMilk();

        }

    }
}

主类测试:

package MultithreadingCase;

public class BoxTest {
    public static void main(String[] args) {
        //创建奶箱对象   用于共享数据
        Box box=new Box();
        //创建生产者对象  把奶箱对象(box)作为构造方法参数传递  调用存储牛奶操作
        Producer p=new Producer(box);
        //创建消费者对象  把奶箱对象(box)作为构造方法参数传递  调用获取牛奶操作
        Customer c=new Customer(box);
        //创建两个线程,把生产者对象和消费者对象作为构造方法参数传进去
        Thread t1=new Thread(p);
        Thread t2=new Thread(c);

        //启动两个线程
        t1.start();
        t2.start();


    }
}

牛奶箱子类:

package MultithreadingCase;

public class Box {

    //定义一个成员变量,用来表示第x瓶牛奶
    private  int milk;
    //定义一个成员变量 用于表示牛奶箱子状态
    private boolean state=false;

    //提供存储牛奶和获取牛奶的操作
public synchronized void putMilk(int milk){
if(state){
    try {
        wait();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}
    //如果没有牛奶  则生产牛奶
    this.milk=milk;
    System.out.println("送奶工人将第"+this.milk+"瓶牛奶放入奶箱");

    //生产完毕  修改牛奶箱子状态
        state=true;
    //唤醒其他等待的线程
    notifyAll();

}

    public synchronized  void getMilk() {
    //如果没有牛奶 等待生产
    if(!state){
        try {
            wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    //如果有牛奶 就消费牛奶
        System.out.println("用户拿到第"+this.milk+"瓶牛奶");
    //  生产完毕  修改牛奶状态
             state=false;
    //唤醒其他等待的线程
        notifyAll();

    }
}

你可能感兴趣的:(JavaSE,多线程,thread,java)