线程之间通讯

之前学习的线程都是单线程执行的,没有设计到线程之间的通讯。线程之间的通讯主要靠以下方法实现。

生产者消费者模式(管程法)

生产者消费者(管程法)实现思路 

  • 创建一个生产者线程:负责生产数据 
  • 创建一个消费者线程:负责消费数据
  • 创建一个数据缓冲区:负责存储生产者生产的数据,并将数据交给消费者消费 

实现代码 

import com.sun.org.apache.xerces.internal.parsers.CachingParserPool;

/**
 * 多线程中的生产者与消费者模式
 */
public class ProducerAndConsumerPattern {
    public static void main(String[] args) {
        Container container = new Container();
        new Producer(container).start();
        new Consumer(container).start();
    }

}

//产品
class Chicken{
    int id;

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

//创建生产者
class Producer extends Thread{
    Container container;

    public Producer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            container.producer(new Chicken(i));
            System.out.println("生产了第" + i +"只鸡" );
        }
    }
}

//创建消费者
class Consumer extends Thread{
    Container container;

    public Consumer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("消费了第" + container.consumer().id + "只鸡");
        }
    }
}

//创建缓冲区
class Container{
    //定义容器的大小
    Chicken[] chickens = new Chicken[10];

    //定义容器计数器
    int count = 0;
    //生产者生产
    public synchronized void producer(Chicken chicken){
        //如果容器满了,就通知消费者消费
        while(count==chickens.length){
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        //生产者生产
        chickens[count] = chicken;
        count++;
        //通知消费者消费
        this.notifyAll();
    }

    //消费者消费
    public synchronized Chicken consumer(){
        //如果容器为空,就通知生产者生产
        while(count==0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        //消费者消费
        count--;
        Chicken chicken = chickens[count];
        //消费以后通知生产者生产
        this.notifyAll();
        return chicken;
    }
}


结果:

因为我发现很多次操作都是生产者现将10只鸡生产好,消费者在消费,我就想可能是因为当消费者线程在阻塞等待的时候(因为count等于0),生产者线程抢到cpu使用权以后在很快的一瞬间就将10只鸡生产好了。所以我为了证明我的猜想,我就在生产者生产鸡的过程中,我让生产好一只鸡以后让生产者睡眠10毫秒: 

import com.sun.org.apache.xerces.internal.parsers.CachingParserPool;

/**
 * 多线程中的生产者与消费者模式
 */
public class ProducerAndConsumerPattern {
    public static void main(String[] args) {
        Container container = new Container();
        new Producer(container).start();
        new Consumer(container).start();
    }

}

//产品
class Chicken{
    int id;

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

//创建生产者
class Producer extends Thread{
    Container container;

    public Producer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            container.producer(new Chicken(i));
            System.out.println("生产了第" + i +"只鸡" );
        }
    }
}

//创建消费者
class Consumer extends Thread{
    Container container;

    public Consumer(Container container) {
        this.container = container;
    }

    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("消费了第" + container.consumer().id + "只鸡");
        }
    }
}

//创建缓冲区
class Container{
    //定义容器的大小
    Chicken[] chickens = new Chicken[10];

    //定义容器计数器
    int count = 0;
    //生产者生产
    public synchronized void producer(Chicken chicken){
        //如果容器满了,就通知消费者消费
        while(count==chickens.length){
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        //生产者生产
        chickens[count] = chicken;
        count++;
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        //通知消费者消费
        this.notifyAll();
    }

    //消费者消费
    public synchronized Chicken consumer(){
        //如果容器为空,就通知生产者生产
        while(count==0){
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        //消费者消费
        count--;
        Chicken chicken = chickens[count];
        //消费以后通知生产者生产
        this.notifyAll();
        return chicken;
    }
}


 结果如下:

竟然出现了先消费的情况。我刚开始还纳闷,为啥我都还没有通知消费者消费(因为要睡眠10毫秒以后再通知),它怎么就先消费了。后来我想了想,因为生产者和消费者是两条线程,我之前的猜测也对——消费者线程先抢到cpu进行消费,但是它一看count等于0,于是就等待生产者生产,生产者抢到cpu以后就开始生产了,然后再通知消费者消费。但是也有可能一开始就是生产者先抢到cpu,他进行生产,生产完一只鸡以后count就变为了1,然后它在睡眠10毫秒。但是在这10毫秒之间,消费者获得了cpu,消费者一看容器里面有一只鸡(count不等于0),她于是就消费了。所以才会出现上面这种情况。

信号灯法 

思想:通过一个标志位来决定由那个线程来处理业务

代码:

public class SigalLampPattern {
    public static void main(String[] args) {
        TV tv = new TV();
        new Play(tv).start();
        new Watch(tv).start();
    }
}



//表演者线程
class Play extends Thread{
    TV tv;

    public Play(TV tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            if(i%2==0){
                tv.play("进击的巨人");
            }else{
                tv.play("火影忍者");
            }
        }
    }
}

//观看者线程
class Watch extends Thread{
    TV tv;

    public Watch(TV tv) {
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            tv.watch();
        }
    }
}

//SigalLamp
class TV{
    //节目
    String item;

    //设置标志
    boolean flag = true;

    //表演者
    public synchronized void play(String item){
        //观看者观看节目,表演者等待
        if(!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println("表演者表演了"+ item);
        this.item = item;
        //通知观看者观看
        this.flag = !flag;
        this.notifyAll();

    }
    //观看者
    public synchronized void watch(){
        //观看者观看
        if(flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println("观看者观看了"+ item);
        //通知表演者表演
        this.flag = !flag;
        this.notifyAll();
    }
}


 结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

咸鱼吐泡泡

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值