线程通信

处理原因:
多个线程并发执行,CPU默认随机切换线程,当处理同一任务时,更好的有规律的调度,需要线程通信,避免对同一共享变量的争夺,使用的手段为:等待唤醒机制

等待唤醒机制

线程之间的通信,更加有效的利用资源

image.png
唤醒一般是唤醒等待时间最长的线程

  • 能获取锁,线程就从WAITING --> RUNNABLE
  • 否则,从wait set出来,又进入entry set,线程WAITING --> BLOCKED

调用wait和notify方法需要注意的细节
image.png

案例

image.png
包子铺线程和包子线程关系 --> 通信(互斥)
使用同步技术,使用锁对象

包子类:

public class BaoZi {

    boolean flag = false;
    String pi;
    String xian;

    public BaoZi() {
    }

    public BaoZi(boolean flag, String pi, String xian) {
        this.flag = flag;
        this.pi = pi;
        this.xian = xian;
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public String getPi() {
        return pi;
    }

    public void setPi(String pi) {
        this.pi = pi;
    }

    public String getXian() {
        return xian;
    }

    public void setXian(String xian) {
        this.xian = xian;
    }
}

包子铺类:

public class Productor extends Thread{
    //1.定一个包子变量
    private BaoZi bz;
    //2.带参数的构造方法,为这个包子变量赋值
    public Productor(BaoZi bz) {
        this.bz = bz;
    }

    @Override
    public void run() {
        int count = 0;
        while (true) {
            //同步技术
            synchronized (bz) {
                if (bz.flag == true) {
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                //被唤醒后,生产包子
                //交替生产两种包子
                if(count % 2 == 0) {
                    //生产薄皮
                    bz.pi = "薄皮";
                    bz.xian = "三鲜馅";
                }else {
                    bz.pi = "冰皮";
                    bz.xian = "牛肉大葱";
                }
                count++;
                System.out.println("包子铺正在生产:" + bz.pi + bz.xian + "包子");
                //生产需要3分钟
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                //修改包子状态
                bz.flag = true;
                //唤醒吃货线程,让吃货线程吃包子
                System.out.println("包子铺已经生产好" + bz.pi + bz.xian + "包子, 吃货可以开始吃");

            }
        }

    }
}

顾客类:

public class Custmer extends Thread{

    private BaoZi bz;

    public Custmer(BaoZi bz) {
        this.bz = bz;
    }
    //线程任务吃包子
    @Override
    public void run() {
        while(true) {
            synchronized (bz) {
                if (bz.flag == true) {

                } else {
                    try {
                        bz.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }

                //被唤醒之后的动作:吃包子
                System.out.println("吃货正在吃" + bz.pi + bz.xian + "包子");
                bz.flag = false;
                //吃货唤醒包子铺线程,生产包子
                bz.notify();
                System.out.println("吃货把" + bz.pi + bz.xian + "包子吃完了,包子铺开始生产包子");
                System.out.println("============");

            }
        }
    }
}

主方法:

public class DemoWAN3Main {
    public static void main(String[] args) {
        //创建包子对象
        BaoZi bz = new BaoZi();
        //创建包子铺线程,生产包子
        new Productor(bz).start();
        //创建吃货线程,开启吃包子
        new Custmer(bz).start();


    }
}

waikiki
4 声望2 粉丝