本帖最后由 小石姐姐 于 2018-9-21 09:23 编辑
经典练习题等待唤醒案例 吃包子 经典 卖包子 吃包子
需求:
定义测试类:
创建一个Object对象, 作为老板(生产者)和顾客(消费者)共用的锁对象
创建顾客(消费者)线程:
使用匿名内部类对象方式, 创建Thread线程, 重写run()方法
run()方法内部定义死循环, 死循环内部使用同步代码块
同步代码块内部打印"[顾客]我要吃包子", 然后通过锁对象调用wait()等待, 然后打印"[顾客]开吃"
创建老板(生产者)线程:
使用匿名内部类对象方式, 创建Thread线程, 重写run()方法
run()方法内部定义死循环, 死循环内部先睡眠5秒模拟做包子耗时
然后定义同步代码块
打印: "[老板]包子做好了, 来吃吧"
然后通过锁对象调用notify()通知顾客继续去吃
运行程序查看效果
顾客线程循环做以下3件事:
1. 打印要吃包子
2. wait()等待
3. 被唤醒后说吃完了
老板线程循环做以下3件事:
1. 睡眠5秒模拟做包子的过程
2. 打印告知顾客包子做好了
3. notify()唤醒顾客
等待唤醒案例: 生产者消费者问题代码实现
需求:
定义测试类:
创建一个Object对象, 作为老板(生产者)和顾客(消费者)共用的锁对象
创建顾客(消费者)线程:
使用匿名内部类对象方式, 创建Thread线程, 重写run()方法
run()方法内部定义死循环, 死循环内部使用同步代码块
同步代码块内部打印"[顾客]我要吃包子", 然后通过锁对象调用wait()等待, 然后打印"[顾客]开吃"
创建老板(生产者)线程:
使用匿名内部类对象方式, 创建Thread线程, 重写run()方法
run()方法内部定义死循环, 死循环内部先睡眠5秒模拟做包子耗时
然后定义同步代码块
打印: "[老板]包子做好了, 来吃吧"
然后通过锁对象调用notify()通知顾客继续去吃
运行程序查看效果
顾客线程循环做以下3件事:
1. 打印要吃包子
2. wait()等待
3. 被唤醒后说吃完了
老板线程循环做以下3件事:
1. 睡眠5秒模拟做包子的过程
2. 打印告知顾客包子做好了
3. notify()唤醒顾客
package com.itheima.demo10.WaitAndNotify.MaiBaoZi;
[Java] 纯文本查看 复制代码 public class Test {
public static void main(String[] args) {
// 创建一个锁对象
Object obj = new Object();
// 创建顾客线程, 实现循环 买包子-等待-吃包子
new Thread(){
@Override
public void run(){
synchronized (obj){
//客户提出需求,买包子
System.out.println("老板买包子,快点");
try {
//1.客户线程进入等待机制,同时释放锁对象,锁对象被老板线程抢夺,执行老板线程
//2.等待机制被老板线程唤醒之后,并且有可能抢夺Cpu执行性权利,并且获取锁对象,就执行下面代码
obj.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("快,端上来,我要吃---");
//等待3秒时间,执行下面代码
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//继续拿着锁对象执行代码
System.out.println("恩恩,真香~~~~~");
}
//出了同步代码作用域,解锁,继续循环
}
}.start();
// 创建老板线程, 实现循环 做包子-通知顾客
new Thread(){
@Override
public void run(){
//锁对象在客户线程等待的时候被释放,老板线程抢夺过来锁对象,并且开始执行代码
synchronized (obj){
//老板线程拿着锁对象,等待5秒时间
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//老板线程继续拿着锁对象,执行代码
System.out.println("您的包子做好了~~");
//执行唤醒机制notify,唤醒等待机制wait,继续执行拿着锁对象执行,直到出了同步代码块作用域
obj.notify();
//会继续拿着锁对象执行下面的代码
System.out.println("会不再执行");
}
//出了作用域之后,将锁对象释放,老板线程和客户线程同时抢夺cpu执行权
}
}.start();
}
}
2.Map两列集合存入类的练习题
请使用Map集合存储自定义数据类型Car做键,对应的价格做值。
并使用keySet和entrySet两种方式遍历Map集合。
package kehoulianxi;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
[Java] 纯文本查看 复制代码 public class Test04 {
public static void main(String[] args) {
Car p1 = new Car("奇瑞", "红色");
Car p2 = new Car("奔驰", "白色");
Car p3 = new Car("劳斯莱斯", "蓝色");
Car p4 = new Car("玉兔车", "五颜六色");
HashMap<Car, Integer> map = new HashMap<>();
map.put(p1, 10000);
map.put(p2, 200000);
map.put(p3, 2000000);
map.put(p4, 500000000);
Set<Map.Entry<Car, Integer>> set1 = map.entrySet();//创建entry对象
for (Map.Entry<Car, Integer> key : set1) {//创建Set集合
Integer value1 = key.getValue();//通过entry对象的getValue方法获取值
Car key1 = key.getKey();//通过entry对象的getgetKey方法获取键
Integer value = map.get(key1);//通过Map集合的get方法写入键获取值
String name = key1.getName();//通过键获取Car对象的get方法获取名字
String color = key1.getColor();//通过键获取Car对象ge方法获取颜色
System.out.println(name + " " + color + " " + value);//遍历打印
}
}
}
Car类
package kehoulianxi;
[Java] 纯文本查看 复制代码 public class Car {
private String name;
private String color;
public Car(String name, String color) {
this.name = name;
this.color = color;
}
public Car() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getColor() {
return color;
}
public void setColor(String color) {
this.color = color;
}
}
|
|