一、基本的买包子案例。
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: 正在等待做包子…
.