线程协作:生产者消费者模式

线程协作:生产者消费者模式:这个模式不是类与类的模式,
 *     是处理线程协作的模型,处理线程通信的问题。
 * 生产者与消费者共享同一资源,并且生产者和消费者之间互相依赖,
 * 互为条件:1.对于生产者,没有生产产品之前,要通知消费者等待,
 *    生产了之后通知消费者消费;
 *          2.对于消费者,在消费之后,要通知生产者已经消费完了,
 *          需要继续生产新产品给消费者;
 * 在生产者消费者问题中,仅有syncharonized是不够的:
 *     1.syncharonized可阻止并发更新同一个共享资源,实现了同步;
 *     2.syncharonized不能来实现不同线程之间的消息传递(通信)

怎么实现通信?

两种通信方法:1.管程法:生产者只负责生产数据模块,消费者只负责
 *    处理数据模块,两个模块之间有个缓冲区,生产者将生产好的数据放
 *    入缓冲区,消费者从缓冲区拿数据。
 *              2.信号灯法,原理和红绿灯一样,借助标志位
 *  Java提供了4个方法解决线程之间的通信问题:
 *    1.wait():表示线程一直等待,直到其他线程通知,与sleep不同,会释放锁。
 *    2.wait(long timeout):指定等待毫秒数
 *    3.notify();唤醒一个处于等待的线程
 *    4.notifyAll():唤醒同一个对象上所以调用wait方法的线程,优先级高的线程
 *    优先调度
 *   注意:这4个方法都是java.lang.Object类的方法;都只能在同步方法会同步块
 *   中使用,否则会抛异常

第一种方式:管程法:模拟生产数据

//生产者
class Productor extends Thread{
    SynContainer container;

    public Productor(SynContainer container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            System.out.println("生产第"+i+"个");
            container.push(new Datas(i));
        }

    }
}
//消费者
class Consumer extends Thread{
    SynContainer container;
    public Consumer(SynContainer container) {
        this.container = container;
    }
    @Override
    public void run() {
        for (int i = 0; i <100 ; i++) {
            System.out.println("消费第"+container.pop().id+"个");
        }

    }
}
//缓冲区
class SynContainer{

    Datas[] datas = new Datas[10];//存储容器
    int count = 0;//计数器
    /*
    存储  生产
    容器有空间可以生产
     */
    public synchronized void push(Datas data){
        if(count == datas.length){//没有空间了
            try {
                this.wait();//线程阻塞  消费者通知生产者停止生产
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
//有空间了 可以生产
        datas[count] = data;
        count ++;
        this.notifyAll();//继续生产
    }
    /*
    获取  消费
    有数据就可以消费  没数据就要等待
     */
    public synchronized Datas pop(){
        if(count==0){//没有数据
            try {
                this.wait();//线程阻塞 生产者通知消费等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
//有数据可以消费
        count--;
        Datas data = datas[count];
        this.notifyAll();//继续消费
        return data;
    }
}
//数据
class Datas{
    int id;

    public Datas(int id) {
        this.id = id;
    }
}

信号灯法:模拟电视

//生产者  演员
class Player extends Thread{
    Tv tv;

    public Player(Tv tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i <20 ; i++) {
            if(i%2==0){
                this.tv.play("王牌对王牌");
            }else{
                this.tv.play("最强大脑");
            }
        }
    }
}
//消费者  观众
class Watcher extends Thread{
    Tv tv;

    public Watcher(Tv tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i <20 ; i++) {
           this.tv.watch();
        }
    }
}
//同一资源
class Tv{
    String voice;
    /*
    信号灯
    flag为真,表示演员表演  观众等待
    flag为假,表示观众观看  演员等待
     */
    boolean flag = true;

    public synchronized void play(String voice){
        if(!flag){
            try {
                this.wait();//观众观看  演员等待
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("表演"+voice);
        this.voice =voice;
        this.notifyAll();
        this.flag = !this.flag;//换信号灯
    }
    public synchronized void watch(){
        if(flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("看到了"+voice);
        this.notifyAll();
        this.flag = !this.flag;
    }
}

结果可以看到,表演了什么就看什么。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值