一、基本的买包子案例。

1.目的,顾客点包子,然后等待,老板做包子,做完后通知顾客(唤醒)。
2. 先了解线程的6种状态.,此处主要了解 Waiting 状态.
  • 一、三种暂停状态
  • 1.sleep Thread.sleep(1000)
  • 2.lock锁,线程安全的3个解决方案
  • 3.wait() :waiting 无限等待,需要notify()方法唤醒
3.案例要求和注意事项
* 二、案例要求:老板线程和顾客线程的通信,
 * 1. 顾客线程: 告知老板需要的包子的数量,调用obj.wait()方法,等待老板做包子
 *      (放弃CPU的执行权力,到Waiting状态)
 * 2. 顾客线程: 花了2秒做包子,然后调用 对应的obj.notify()方法,唤醒对应的等待线程
 * 三:注意:
 * 1.老板和顾客的线程使用同步代码块包裹,防止线程保证等待和唤醒只有一个在执行
 * 2.同步obj.wait() 和 obj.notify()的 obj 对象必须相同,对应
 * 3. wait()和 notify() 是Object类中的方法.

4.代码

Main.java

package Java学习.Java高级.多线程.等待唤醒案例wait.模板;

/**
 * 目的,顾客点包子,然后等待,老板做包子,做完后通知顾客(唤醒)。
 * 一、三种暂停状态
 * 1.sleep Thread.sleep(1000)
 * 2.lock锁,线程安全的3个解决方案
 * 3.wait()  :waiting 无限等待,需要notify()方法唤醒
 * 二、案例要求:老板线程和顾客线程的通信,
 * 1. 顾客线程: 告知老板需要的包子的数量,调用obj.wait()方法,等待老板做包子
 * (放弃CPU的执行权力,到Waiting状态)
 * 2. 顾客线程: 花了2秒做包子,然后调用 对应的obj.notify()方法,唤醒对应的等待线程
 * 三:注意:
 * 1.老板和顾客的线程使用同步代码块包裹,防止线程保证等待和唤醒只有一个在执行
 * 2.同步obj.wait() 和 obj.notify()的 obj 对象必须相同,对应
 * 3. wait()和 notify() 是Object类中的方法.
 */
public class Demo {
    public static void main(String[] args) {
        Object object = new Object();
        //Customer----------
        new Thread(new Runnable() {
            @Override
            public void run() {
                //进入同步代码块.获取object.
                synchronized (object) {
                    System.out.println("Customer: 提交包子套餐");
                    try {
                        object.wait();
                        System.out.println("Customer:包子获得成功");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //出来同步代码块,返回object
            }
        }).start();
        //卖家
        new Thread(new Runnable() {
            @Override
            public void run() {
                //进入同步代码块,获得object对象.
                synchronized (object) {
                    try {
                        System.out.println("卖家: 订单获取成功,正在做包子...");
                        Thread.sleep(1000);
                        System.out.println("卖家:包子制作成功,下一位");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } finally {
                        object.notify();
                    }
                }
            }
        }).start();
    }
}

输出:
Customer: 提交包子套餐
卖家: 订单获取成功,正在做包子…
卖家:包子制作成功,下一位
Customer:包子获得成功

Process finished with exit code 0

二、高级的包子.

1.步骤,原理 ,注意事项
/**
 * 锁lock 案例失败,使用synchronized 来完成.
 * 一、要求:Seller等待,判断包子不存在,,Customer提交申请,
 *          Customer等待,Seller开始做包子,完成后,激活Customer拿走包子,下一位一共10个包子,
 * 二、步骤
 * 1.新建包子类,定义bonFlag包子是否存在,和包子名称.包子数量NumberOfBun
 * 2.新建商家Seller类 ,
 *      1.带参数的构造,传入包子bon 对象.
 *      2.再Number中遍历,进入线程0,如果包子IsBunExist()就等wait()2的他吃完.
 *      3.没有包子或者吃完后,做包子,然后 IsBunExist() = true
 * 3.新建顾客Customer类
 *      1,传入参数 bun 对象
 *      2.在Number中遍历,进入线程1,如果没有有包子IsBunExist()就wait()1,等他做好.
 *      3.有包子或者吃完后,,然后 IsBunExist() = false;
 * 问题:
 * 1. 一个 bun 对象为何可以在2个线程内同时运行,但是Lock.lock(),unlock()却不行,可能没试过.试试。
 */
2 。代码

Main.java

package Java学习.Java高级.多线程.等待唤醒案例wait.模仿案例2高级包子;

/**
* 锁lock 案例失败,使用synchronized 来完成.
* 一、要求:Seller等待,判断包子不存在,,Customer提交申请,
*          Customer等待,Seller开始做包子,完成后,激活Customer拿走包子,下一位一共10个包子,
* 二、步骤
* 1.新建包子类,定义bonFlag包子是否存在,和包子名称.包子数量NumberOfBun
* 2.新建商家Seller类 ,
*      1.带参数的构造,传入包子bon 对象.
*      2.再Number中遍历,进入线程0,如果包子IsBunExist()就等wait()2的他吃完.
*      3.没有包子或者吃完后,做包子,然后 IsBunExist() = true
* 3.新建顾客Customer类
*      1,传入参数 bun 对象
*      2.在Number中遍历,进入线程1,如果没有有包子IsBunExist()就wait()1,等他做好.
*      3.有包子或者吃完后,,然后 IsBunExist() = false;
* 问题:
* 1. 一个 bun 对象为何可以在2个线程内同时运行,但是Lock.lock(),unlock()却不行,可能没试过.试试。
*/
public class Demo {
   public static void main(String[] args) {
       Bun bun = new Bun();
       new Thread(new Seller(bun)).start();
       new Thread(new Customer(bun)).start();
   }

}

Bun.java

package Java学习.Java高级.多线程.等待唤醒案例wait.模仿案例2高级包子;

/**
 *  * 二、步骤
 *  * 1.新建包子类,定义bonFlag包子是否存在,和bonOrderFlag订单是否存在.和包子名称.
 *  * 2.新建商家Seller类 ,
 *  *      1.带参数的构造,传入包子bon 对象. 线程函数,
 *  *      2.判断bonOrderFlag 是否存在,false ,bon.wait(),true 就做包子,sleep(1000)
 *  *      3.做完后,bonFlag = true ,
 *  * 3.新建Customer类:
 *  *      1.传入包子对象,进入线程
 *  *      2.判断bonFlag ,if false ,提交订单,bonOrderFlag = true,然后等待,bon.wait()
 */
public class Bun {
    private String bunType = "白菜包子";
    private int numberOfBun = 10;
    private boolean isBunExist = false;

    public String getBunType() {
        return bunType;
    }

    public int getNumberOfBun() {
        return numberOfBun;
    }

    public boolean isBunExist() {
        return isBunExist;
    }

    public void setBunType(String bunType) {
        this.bunType = bunType;
    }

    public void setNumberOfBun(int numberOfBun) {
        this.numberOfBun = numberOfBun;
    }

    public void setBunExist(boolean bunExist) {
        isBunExist = bunExist;
    }
}

Customer.java

package Java学习.Java高级.多线程.等待唤醒案例wait.模仿案例2高级包子;

/**
 *  * 二、步骤
 *  * 1.新建包子类,定义bonFlag包子是否存在,和bonOrderFlag订单是否存在.和包子名称.
 *  * 2.新建商家Seller类 ,
 *  *      1.带参数的构造,传入包子bon 对象. 线程函数,
 *  *      2.判断bonOrderFlag 是否存在,false ,bon.wait(),true 就做包子,sleep(1000)
 *  *      3.做完后,bonFlag = true ,
 *  * 3.新建Customer类:
 *  *      1.传入包子对象,进入线程
 *  *      2.判断bonFlag ,if false ,提交订单,bonOrderFlag = true,然后等待,bon.wait()
 */
public class Customer implements Runnable{
    Bun bun ;

    public Customer(Bun bun) {
        this.bun = bun;
    }

    @Override
    public void run() {
        //吃包子的次数.
        for (int i = 0; i < bun.getNumberOfBun(); i++) {
            //进入线程
            synchronized (bun){
                //没有就等包子
                System.out.println("线程:Customer--"+Thread.currentThread());
                if (bun.isBunExist() == false){
                    System.out.println("Customer: 正在等待做包子...");
                    try {
                        bun.wait();//正在等待 1.
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("Customer: 正在吃包子...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Customer:包子已经吃完");
                bun.setBunExist(false);
                bun.notify();//释放 2.
            }
        }
    }
}

Seller.java

package Java学习.Java高级.多线程.等待唤醒案例wait.模仿案例2高级包子;

/**
 * * 二、步骤
 * * 1.新建包子类,定义bonFlag包子是否存在,.和包子名称.
 * * 2.新建商家Seller类 ,
 * *      1.带参数的构造,传入包子bon 对象. 线程函数,
 * *      2.判断包子是否存在,false ,bon.wait(),true 就做包子,sleep(1000)
 * *      3.做完后,bonFlag = true ,
 * * 3.新建Customer类:
 * *      1.传入包子对象,进入线程
 * *      2.判断bonFlag ,if false ,提交订单,bonOrderFlag = true,然后等待,bon.wait()
 */
public class Seller implements Runnable {
    private Bun bun;

    public Seller(Bun bun) {
        this.bun = bun;
    }

    @Override
    public void run() {
        //如果包子数量未满就,进入线程.
        for (int i = 0; i < bun.getNumberOfBun(); i++) {
            //进入线程
            synchronized (bun) {

                //如果包子还没吃完就等待wait()
                if (bun.isBunExist()) {
                    try {
                        System.out.println("Seller: 正在等待包子吃完.");
                        bun.wait();//正在等待 2.
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //等待后做包子,或者直接做包子,不用使用else{
                System.out.println("------------------"+i+"---------------------");
                System.out.println("线程:Seller--"+Thread.currentThread());
                System.out.println("Seller: 正在做" + bun.getBunType() + "...");
                try {
                    Thread.sleep(1000);
                    System.out.println("Seller: 完成");
                    bun.setBunExist(true);//设置bunExist = true
                    bun.notify();//释放1.
                } catch (InterruptedException e) {
                    e.printStackTrace();

                }
            }
        }
        //最后包子做完了就,完成订单.
        System.out.println("Seller:您的订单已经完成.===");
    }
}

输出::
------------------0---------------------
线程:Seller–Thread[Thread-0,5,main]
Seller: 正在做白菜包子…
Seller: 完成
Seller: 正在等待包子吃完.
线程:Customer–Thread[Thread-1,5,main]
Customer: 正在吃包子…
Customer:包子已经吃完
线程:Customer–Thread[Thread-1,5,main]
Customer: 正在等待做包子…
------------------1---------------------
线程:Seller–Thread[Thread-0,5,main]
Seller: 正在做白菜包子…
Seller: 完成
Seller: 正在等待包子吃完.
Customer: 正在吃包子…
Customer:包子已经吃完
线程:Customer–Thread[Thread-1,5,main]
Customer: 正在等待做包子…
------------------2---------------------
线程:Seller–Thread[Thread-0,5,main]
Seller: 正在做白菜包子…
Seller: 完成
Seller: 正在等待包子吃完.
Customer: 正在吃包子…
Customer:包子已经吃完
线程:Customer–Thread[Thread-1,5,main]
Customer: 正在等待做包子…

.。。。
。。。。
------------------10---------------------
线程:Seller–Thread[Thread-0,5,main]
Seller: 正在做白菜包子…
Seller: 完成
Seller: 正在等待包子吃完.
Customer: 正在吃包子…
Customer:包子已经吃完
线程:Customer–Thread[Thread-1,5,main]
Customer: 正在等待做包子…
.