ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

生产者消费者模式

2021-10-25 11:01:47  阅读:214  来源: 互联网

标签:play 消费者 生产者 watch 模式 tv produce chicken consume


生产者消费者模式

生产者消费者模式是线程协作的一种情况,意思是线程1生产资源,线程2消费资源,有资源时才能消费,没有资源时需要生产。

运作生产者消费者模式有两种办法:管程法和信号灯法。

管程法

管程法建造一个缓冲区,让生产者生产的资源存储在缓冲区,消费者从缓冲区中获取资源,而不是直接从生产者那里获取。

以下代码演示管程法:

package com.cxf.multithread.produce_consume;

import java.awt.*;

public class TestForProduceConsume {
    public static void main(String[] args) {
        Buffer buffer = new Buffer();
        new Producer(buffer).start();
        new Consumer(buffer).start();
    }
}

class Producer extends Thread {
    Buffer buffer;
    public Producer(Buffer buffer) {
        this.buffer =buffer;
    }
    public void run() {
        for (int i = 1; i <= 100; i++) {
            try {
                buffer.push(new Chicken(i));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("produce a NO."+i+" chicken");
        }
    }

}

class Consumer extends Thread {
    Buffer buffer;
    public Consumer(Buffer buffer) {
        this.buffer =buffer;
    }

    public void run() {
        for (int i = 1; i <= 20; i++) {
            try {
                System.out.println("consume a NO."+buffer.pop().id+" chicken");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

class Chicken{
    int id;
    Chicken(int id) {
        this.id = id;
    }
}

class Buffer {
    Chicken[] chickens = new Chicken[10];
    int count = 0;
    public synchronized void push(Chicken chicken) throws InterruptedException {
        if (count == chickens.length) {
            this.wait();
        }
        chickens[count] = chicken;
        count++;
        this.notifyAll();
    }

    public synchronized Chicken pop() throws InterruptedException {
        if (count == 0) {
            this.wait();
        }

        count--;
        Chicken chicken = chickens[count];

        notifyAll();
        return chicken;
    }
}

输出结果:

produce a NO.1 chicken
produce a NO.2 chicken
produce a NO.3 chicken
produce a NO.4 chicken
produce a NO.5 chicken
produce a NO.6 chicken
produce a NO.7 chicken
produce a NO.8 chicken
produce a NO.9 chicken
produce a NO.10 chicken
produce a NO.11 chicken
consume a NO.10 chicken
consume a NO.11 chicken
produce a NO.12 chicken
consume a NO.12 chicken
produce a NO.13 chicken
consume a NO.13 chicken
consume a NO.14 chicken
consume a NO.9 chicken
produce a NO.14 chicken
consume a NO.8 chicken
consume a NO.15 chicken
produce a NO.15 chicken
produce a NO.16 chicken
consume a NO.7 chicken
produce a NO.17 chicken
consume a NO.17 chicken
consume a NO.18 chicken
produce a NO.18 chicken
consume a NO.16 chicken
produce a NO.19 chicken
produce a NO.20 chicken
consume a NO.19 chicken
consume a NO.20 chicken
consume a NO.6 chicken
consume a NO.5 chicken
consume a NO.4 chicken
consume a NO.3 chicken
consume a NO.2 chicken
consume a NO.1 chicken

上面的代码中,消费者线程的任务是需要消费20只鸡,生产者线程的任务是生产20只鸡,缓冲区能容纳10只已生产未消费的鸡。

生产的资源和消费的资源数要相等,否则导致其中一方线程结束,而另一方一直在缓冲区等待。

信号灯法

信号灯法使用标志变量来控制哪个线程需要等待,哪个线程需要唤醒。

以下代码演示如何使用信号灯法:

package com.cxf.multithread.produce_consume;

public class TestForFlag {
    public static void main(String[] args) {
        TV tv = new TV();
        new Player(tv).start();
        new Watcher(tv).start();
    }
}

class Player extends Thread {
    TV tv;
    public Player(TV tv) {
        this.tv = tv;
    }
    public void run() {
        for (int i = 0; i < 10; i++) {
            if(i%2 == 0) {
                try {
                    this.tv.play("Spring night");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }else {
                try {
                    this.tv.play("Harry Porter");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}

class Watcher extends Thread{
    TV tv;
    public Watcher(TV tv) {
        this.tv = tv;
    }

    public void run() {
        for (int i = 0; i < 10; i++) {
            try {
                tv.watch();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class TV{

    String content;
    boolean flag = true;

    public synchronized void play(String content) throws InterruptedException {

        if(!flag) {
            this.wait();
        }
        System.out.println("play a " + content);
        notifyAll();
        this.content = content;
        this.flag = !this.flag;
    }

    public synchronized void watch() throws InterruptedException {
        if (flag) {
            this.wait();
        }
        System.out.println("watch a " +content);
        notifyAll();
        this.flag = !this.flag;
    }
}

输出结果:

play a Spring night
watch a Spring night
play a Harry Porter
watch a Harry Porter
play a Spring night
watch a Spring night
play a Harry Porter
watch a Harry Porter
play a Spring night
watch a Spring night
play a Harry Porter
watch a Harry Porter
play a Spring night
watch a Spring night
play a Harry Porter
watch a Harry Porter
play a Spring night
watch a Spring night
play a Harry Porter
watch a Harry Porter

在生产者生产之后,和消费者消费之后才会分别改变标志位,让生产者和消费者的事件能够交替进行。

标签:play,消费者,生产者,watch,模式,tv,produce,chicken,consume
来源: https://www.cnblogs.com/cxf-tech/p/15457466.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有