其他分享
首页 > 其他分享> > 第6组markdown

第6组markdown

作者:互联网

用java多线程实现生产者消费者同步问题

组员:师浩东 魏昕宇 郑旭根

目录


一、思路分析

首先由于是生产者生产出产品,消费者才能消费
所以生产者消费者问题,实际上主要包含了两类线程。
一类是生产者线程用于生产产品,一类是消费者线程用于消费产品。
为解决这个问题,我们假设有一个仓库,生产者生产出产品之后就直接放在仓库里,并不需要关心消费者的行为,消费者只需要从仓库中消费产品即可,并不需要关心生产者的行为

二、java代码实现与思路

流程图:

在这里插入图片描述

1.创建仓库类

所以首先我们新建一个类来作为仓库,其中肯定需要定义放入产品和取出产品的方法

其中为了防止同一件产品被多名消费者消费,需要用synchronized关键字给取的方法上锁,也就是说,当有一个消费者线程抢占到CPU执行权之后,其他线程就不能调用消费(put)这个方法。

代码如下:

public class Box {
    //定义一个成员变量,表示第x个产品
    private int product;
    //定义一个成员变量,表示仓库的状态
    private boolean state=false;
    //上锁
    //一个线程访问一个对象中的synchronized(this)同步代码块时,其他试图访问该对象的线程将被阻塞
    public synchronized void put(int product){
        //如果有产品,等待消费
        if (state==true){
            try{
                wait();
            }catch (InterruptedException e){
                e.printStackTrace();
            }
        }
        //如果没有产品,等待生产
        this.product=product;
        System.out.println("生产者将第"+this.product+"件产品放入仓库");
        //消费完毕之后,修改仓库状态
        state=true;
        //唤醒其他等待的线程
        notifyAll();
    }
    public synchronized void get(){
        //如果没有产品,等待生产
        if (!state){
             try {
                 wait();
             }catch (InterruptedException e){
                 e.printStackTrace();
             }
        }
        System.out.println("消费者消费第"+this.product+"件产品");
        //消费完毕之后,修改仓库状态
        state=false;
        //解锁唤醒其他等待线程
        notifyAll();
    }
}

2.创建生产者类

创建生产者类实现了Runnable接口,在类里边定义了带参构造方法,参数类型为仓库类
这样就可以在主方法执行时,启动线程,调用这个类中的run方法,然后生产时直接可以调用仓库类中的put方法把产品放入仓库。

public class Producer implements Runnable{
    private Box box;
    public Producer(Box b){
        this.box=b;
    }
    @Override
    public void run() {
        //假设这个生产者一天只能生产五件给消费者
        for (int i=1;i<=5;i++){
            box.put(i);
        }
    }
}

3.创建消费者类

创建消费者类实现了Runnable接口,在类里边定义了带参构造方法,参数类型为仓库类
这样就可以在主方法执行时,启动线程,调用这个类中的run方法,然后消费时直接可以调用仓库类中的get方法消费产品。

public class Customer implements Runnable{
    private Box box;
    public Customer(Box box){
        this.box=box;
    }
    @Override
    public void run() {
        while (true){
            box.get();
        }
    }
}


4.创建测试类实现代码

public class Main {
    public static void main(String[] args) {
        //创建仓库对象,作为共享区域
        Box box=new Box();
        //创建生产者对象,把仓库作为构造方法的参数传递,因为在这个类中要调用存储产品的操作
        Producer producer=new Producer(box);
        //创建消费者对象,把仓库作为构造方法参数的传递,因为在这个类中要调用获取产品的操作
        Customer customer=new Customer(box);
        //创建线程对象,分别把生产者对象和消费者对象作为构造方法参数传递
        Thread thread1=new Thread(producer);
        Thread thread2=new Thread(customer);
        thread1.start();
        thread2.start();
    }
}

运行结果为:

"D:\IDEA\IntelliJ IDEA 2019.3.3\jbr\bin\java.exe" "-javaagent:D:\IDEA\IntelliJ IDEA 2019.3.3\lib\idea_rt.jar=5125:D:\IDEA\IntelliJ IDEA 2019.3.3\bin" -Dfile.encoding=UTF-8 -classpath D:\IdeaJavaCode\语法2\out\production\语法2 多线程.Main
生产者将第1件产品放入仓库
消费者消费第1件产品
生产者将第2件产品放入仓库
消费者消费第2件产品
生产者将第3件产品放入仓库
消费者消费第3件产品
生产者将第4件产品放入仓库
消费者消费第4件产品
生产者将第5件产品放入仓库
消费者消费第5件产品

根据结果可以看出,运行结果确实是生产者生产一个产品消费者就可以消费一个产品,并且没有出现几个消费者同时消费一个产品的情况,所以此代码完成了生产者消费者问题。

标签:markdown,消费者,仓库,件产品,生产者,线程,public
来源: https://blog.csdn.net/weixin_49053303/article/details/120587769