线程通信概念的理解

线程等待唤醒机制。

用到的API, 下面的方法都是Object中的。
    void wait​(): 让当前的线程等待。
    void notify​(): 随机唤醒一个线程
    void notifyAll​(): 唤醒所有的线程。

上面这些方法虽然是Object中的方法,但是不能通过对象直接去调用
这些方法一定要放在同步代码块中,并且使用锁对象(对象监视器)去调用。

当一个线程调用wait方法后,会释放自己的锁。

waitsleep的方法的区别了:
    wait方法会释放锁
    sleep方法不会释放锁。

案例:
包子铺  吃货。 包子铺做包子,做完包子通知(notify)吃货吃包子。包子铺等待吃货吃完,然后通知(notif)包子铺做包子。当两个线程共享同一种数据时,容易出现线程安全问题。


1.定义包子类。该类作为锁对象。

public class BaoZi {
    //定义成员变量,表示包子是否存在
    public  boolean flag=false;
    public String xianer;
}
2.定义包子铺和。吃货类:‘传参:创建的包子类作为参数,传到包子铺和吃货类。用变量接收,这样可以保证,包子铺和吃货吃的是同一个包子
public class BaoZiPu implements Runnable {
    private BaoZi baoZi;//定义一个成员变量,

    public BaoZiPu(BaoZi baoZi) {//构造方法,当我创建包子铺的对象时候就可以从外界传入一个
//     包子对象,然后把包子对象赋值给成员变量,这样就可以保证,包子铺里面的包子和吃货里面的包
//    子是同一个包子
        this.baoZi = baoZi;
    }

    //包子铺线程执行的任务
    @Override
    public void run() {
        while (true) {
            //因为包子铺和吃货所用的包子是同一个,所以可以把包子当成锁对象
            synchronized (baoZi) {//如果还有包子,则包子铺不做包子,等待吃货吃完
                if (baoZi.flag) {
                    //调用wait方法,让包子铺这个线程等待
                    try {
                        baoZi.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //如果没有包子,就生产包子,
                System.out.println("包子铺生产了一个包子。快来吃");
                baoZi.flag = true;//表示包子已经生成完成了
                //包子铺生产完包子,提醒吃货去吃包子
                baoZi.notify();
            }
        }
    }
}
public class ChiHuo implements Runnable {
    private BaoZi baoZi;

    public ChiHuo(BaoZi baoZi) {
        this.baoZi = baoZi;
    }

    //吃货线程要做的任务,吃包子
    @Override
    public void run() {
        while (true) {
            synchronized (baoZi) {
                if (!baoZi.flag) {
                    //如果没有包子。则调用wait方法等待
                    try {
                        baoZi.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
                //如果有包子,那就吃
                baoZi.xianer="大饼";
                System.out.println("吃货把这个包子吃完了,吃的是" +baoZi.xianer + "的包子");
                baoZi.flag = false;
                //如果吃完就通知包子铺线程去做包子
                baoZi.notify();
            }
        }
    }
}
3 测试类
package cn.itcast.demo01_thread;

/*
    线程等待唤醒机制。
    用到的API, 下面的方法都是Object中的。
        void wait​(): 让当前的线程等待。
        void notify​(): 随机唤醒一个线程
        void notifyAll​(): 唤醒所有的线程。

    上面这些方法虽然是Object中的方法,但是不能通过对象直接去调用
    这些方法一定要放在同步代码块中,并且使用锁对象(对象监视器)去调用。

    当一个线程调用wait方法后,会释放自己的锁。

    waitsleep的方法的区别了:
        wait方法会释放锁
        sleep方法不会释放锁。
 */
public class Demo01Test {
    public static void main(String[] args) {
        //新建一个包子对象
        BaoZi baozi = new BaoZi();
        //新建一个包子铺对象
        BaoZiPu baoZiPu = new BaoZiPu(baozi);
        //新建一个吃货对象
        ChiHuo chiHuo = new ChiHuo(baozi);
        //分别创建两个线程去执行这两个任务
        new Thread(baoZiPu).start();
        new Thread(chiHuo).start();

    }
}

猜你喜欢

转载自blog.csdn.net/qq_28761767/article/details/81038870