プロデューサーとコンシューマーのケース

生産者/消費者問題の原因は、もともと蒸し饅頭と蒸し饅頭でしたが、蒸し饅頭には、饅頭の生成と消費の2つの方法がありました。ループでパンを作り、同時にループパンを食べたい場合は、単一のスレッドを使用することはできません。マルチスレッドを導入して、2つのメソッドを同時に実行できるようにします。

部分的な結果のスクリーンショット(バッファプールに入れることができるパンは1つだけです)

プロデューサーコンシューマー実装バージョン1:

import java.util.Random;
public class Test {
    public static void main(String[] args) {
        Box box = new Box();//创造一个蒸笼
        //创建生产者子类对象
        Producer producer = new Producer(box);
        //创建消费者子类对象
        Consumer consumer = new Consumer(box);
        //创建线程对象并起名,两个生产者,两个消费者
        Thread p1 = new Thread(producer, "生产者1");
        Thread p2 = new Thread(producer, "生产者2");
        Thread c1 = new Thread(consumer, "消费者1");
        Thread c2 = new Thread(consumer, "消费者2");
        //启动线程
        p1.start();
        p2.start();
        c1.start();
        c2.start();
    }
}
class Box {//蒸笼类,一次只能放一个包子
    private Food food;//包子对象
    void setFood(Food newFood) {//生产包子
        //只有生产者会调用生产包子的方法,输出是哪个生产者生产的包子
        food = newFood;//把生产的包子放进蒸笼
        System.out.println(Thread.currentThread().getName() + "生产了" + food);
    }
    void eatFood() {//吃包子
        //只有消费者才执行吃包子的方法,输出是哪个消费者吃的包子
        System.out.println(Thread.currentThread().getName() + "吃" + food);
        food = null;//吃完包子,把包子置为null
    }
    boolean isEmpty() {//判断蒸笼是否为空
        return food == null;//吃完包子后消费者会把包子置为null
    }
}
class Food {//包子类
    String name;//包子名字
    int price;//包子价格
    public Food() {
    }
    public Food(String name, int price) {
        this.name = name;
        this.price = price;
    }
    @Override
    public String toString() {
        return "Food{" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}
class Producer implements Runnable {//生产者
    Box box;
    public Producer() {
    }
    public Producer(Box box) {
        this.box = box;
    }
    Food[] foods = {new Food("杭州小笼包", 5),
            new Food("天津狗不理", 30), new Food("奶黄包", 2)};
    Random random = new Random();//用来随机选择生产哪种包子
    @Override
    public void run() {
        while (true) {//一直生产包子
            synchronized (box) {//用box做锁对象是为了能唤醒阻塞在蒸笼对象上的消费者
                if (box.isEmpty()) {//蒸笼空了,可以放包子了
                    int sort = random.nextInt(foods.length);//生成【0,foods.length)的整数
                    box.setFood(foods[sort]);//把第sort种包子放入蒸笼
                    box.notifyAll();//唤醒阻塞在蒸笼对象上的消费者来吃包子,
                    // 不用notify()为了防止有多个生产者,想唤醒消费者,实际只唤醒其它生产者,最终全部线程都在wait状态
                } else {//蒸笼有包子
                    try {
                        box.wait();//生产者自己阻塞自己
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}
class Consumer implements Runnable {//消费者
    Box box;
    public Consumer(Box box) {
        this.box = box;
    }
    public Consumer() {
    }
    @Override
    public void run() {
        while (true) {//一直吃包子
            synchronized (box) {//用box做锁对象是为了能唤醒阻塞在蒸笼对象上的生产者
                if (!box.isEmpty()) {//蒸笼非空,可以吃包子
                    box.eatFood();//吃完包子,蒸笼里的food=null
                    box.notifyAll();//唤醒阻塞在蒸笼对象上的生产者做包子,
                    // 不用notify(),为了防止有多个消费者,想唤醒生产者,实际只唤醒是其它消费者,最后这个程序终止
                } else {//蒸笼空
                    try {
                        box.wait();//消费者自己阻塞自己
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }
}

プロデューサーコンシューマー実装バージョン2:

import java.util.Random;

public class Test {
    public static void main(String[] args) {
        Box box = new Box();//创造一个蒸笼
        //创建生产者子类对象
        Producer producer = new Producer(box);
        //创建消费者子类对象
        Consumer consumer = new Consumer(box);
        //创建线程对象并起名,两个生产者,两个消费者
        Thread p1 = new Thread(producer, "生产者1");
        Thread p2 = new Thread(producer, "生产者2");
        Thread c1 = new Thread(consumer, "消费者1");
        Thread c2 = new Thread(consumer, "消费者2");
        //启动线程
        p1.start();
        p2.start();
        c1.start();
        c2.start();
    }
}
class Box {//蒸笼类,一次只能放一个包子
    private Food food;//包子对象
    synchronized void setFood(Food newFood) {//把生产者输入的包子放入蒸笼
        // synchronized修饰普通方法锁对象是当前对象,锁住其它生产者
        //只有生产者会调用生产包子的方法
        if (food == null) {//蒸笼空了,可以放包子了
            food = newFood;//包子放入蒸笼
            // 输出是哪个生产者生产的包子
            System.out.println(Thread.currentThread().getName() + "做了" + food);
            this.notifyAll();//唤醒阻塞在蒸笼对象上的消费者来吃包子,
            // 不用notify()是为了防止有多个生产者,像唤醒消费者实际只唤醒其它生产者,最后全部线程都在wait状态
        } else {//蒸笼有包子
            try {
                wait();//相当于this.wait(),生产者自己阻塞自己
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    synchronized void eatFood() {//吃包子,锁住其它消费者
        //只有消费者才执行吃包子的方法
        //用box做锁对象是为了能唤醒阻塞在蒸笼对象上的生产者
        if (food != null) {//蒸笼非空,可以吃包子
            // 输出是哪个消费者吃的包子
            System.out.println(Thread.currentThread().getName() + "吃掉" + food);
            food = null;//吃完包子,把包子置为null
            this.notifyAll();//唤醒阻塞在蒸笼对象上的生产者做包子,
            // 不用notify()是为了防止有多个消费者,像唤醒生产者,实际只唤醒是它消费者,最后全部线程都是wait
        } else {//蒸笼空
            try {
                this.wait();//消费者自己阻塞自己
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}
class Food {//包子类
    String name;//包子名字
    int price;//包子价格
    public Food() {
    }
    public Food(String name, int price) {
        this.name = name;
        this.price = price;
    }
    @Override
    public String toString() {
        return "包子 {" +
                "name='" + name + '\'' +
                ", price=" + price +
                '}';
    }
}
class Producer implements Runnable {//生产者
    Box box;
    public Producer() {
    }
    public Producer(Box box) {
        this.box = box;
    }
    Food[] foods = {new Food("杭州小笼包", 5),
            new Food("天津狗不理", 30), new Food("奶黄包", 2)};
    Random random = new Random();//用来随机选择生产哪种包子
    @Override
    public void run() {
        while (true) {//一直生产包子
            int sort = random.nextInt(foods.length);//生成【0,foods.length)的整数
            box.setFood(foods[sort]);//把第sort种包子放入蒸笼
        }
    }
}
class Consumer implements Runnable {//消费者
    Box box;
    public Consumer(Box box) {
        this.box = box;
    }
    public Consumer() {
    }
    @Override
    public void run() {
        while (true) {//一直吃包子
            box.eatFood();
        }
    }
}

誤ったウェイクアップ:ウェイクアップすべきではないスレッドをウェイクアップします(たとえば、コンシューマー1はnotifyAll()を使用してプロデューサー1をウェイクアップしたいが、コンシューマー2もウェイクアップしたい)

おすすめ

転載: blog.csdn.net/qq_43496435/article/details/114059500