线程通信(生产者消费者问题)

生产者消费者问题

在生产者消费者问题中,仅有synchronized是不够的:

  • synchronized可阻止并发更新同一个共享资源,实现了同步

  • synchronized不能实现不同线程之间的信息传递(通信)

线程通信方法

注意:均是Object类的方法,都只能在同步方法或者同步代码块中使用,否则会抛出异常IIIlegalMonitorStateException

解决方法1

并发协作模式“生产者/消费者模式”——>管程法

生产者将生产好的数据放入缓冲区消费者从缓冲区拿出数据

public class TestPC {
    public static void main(String[] args) {
        Container container = new Container();

        new Productor(container).start();
        new Consumer(container).start();
    }
}
//1、需要生产者、消费者、产品和缓冲区
class Productor extends Thread{
    Container container;
    Productor(Container container){
        this.container = container;
    }
    //生产
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            Chickens chicken = new Chickens(i);
            try {
                container.put(chicken);
                System.out.println("生产者生产了第"+chicken.ID+"只鸡");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Consumer extends Thread{
    Container container;
    Consumer(Container container){
        this.container = container;
    }
    @Override
    public void run() {
        for (int i = 1; i <= 100; i++) {
            try {
                Chickens chicken = container.pop();
                System.out.println("消费者消费了第"+chicken.ID+"只鸡");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Chickens{
    int ID;//鸡的编号
    Chickens(int ID){
        this.ID = ID;
    }
}

class Container{
    //定义一个缓冲区
    Chickens[] chickens = new Chickens[10];
    int count = 0;//计数器
    //2、往缓冲区里面放东西,注意是同步方法
    public synchronized void put(Chickens chicken) throws InterruptedException {
        //如果缓冲区满了,就通知生产者等待
        if(count == chickens.length){
            this.wait();
        }
        //生产者生产并通知消费者消费
        chickens[count] = chicken;
        count++;
        this.notifyAll();
    }
    //3、取出缓冲区东西
    public synchronized Chickens pop() throws InterruptedException {
        //如果缓冲区空了,消费者等待
        if(count == 0){
            this.wait();
        }
        //消费者消费并通知生产者生产
        count--;
        Chickens chicken = chickens[count];
        this.notifyAll();
        return chicken;
    }
}

解决方法2

并发协作模式“生产者/消费者模式”——>信号灯法

//信号灯法:标志位
public class TestPC2 {
    public static void main(String[] args) {
        TV tv = new TV();

        new Actor(tv).start();
        new Watcher(tv).start();
    }
}
//1、演员表演节目,观众观看节目
//演员
class Actor extends Thread{
    TV tv;
    Actor(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 Watcher extends Thread{
    TV tv;
    Watcher(TV tv){
        this.tv = tv;
    }

    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            tv.watch();
        }
    }
}
//节目
class TV{
    String programme;//节目名字
    //2、标志位 演员表演,观众等待T
    //        演员等待,观众看F
    boolean flag = true;

    //3、表演同步方法
    public synchronized void play(String programme){
        //如果标志位为假,演员等待
        if(!flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //演员表演,通知观众观看,改变标志位
        this.programme = programme;
        System.out.println("演员表演了"+programme);
        this.flag = !this.flag;
        this.notifyAll();
    }

    //4、观看同步方法
    public synchronized void watch(){
        //如果标志位为真,观众等待
        if(flag){
            try {
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //观众观看,通知演员表演,改变标志位
        System.out.println("观众观看了"+this.programme);
        this.flag = !this.flag;
        this.notifyAll();
    }

}
posted @ 2022-11-11 15:04  奚罗罗  阅读(17)  评论(0编辑  收藏  举报