首先 我们创建一个包
在包下创建
四个类
首先是奶箱类 milkBox 在业务中充当数据的存储类
参考代码如下
public class milkBox {
private int milk;
public void put (int milk){
this.milk = milk;
System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱");
}
public void get(){
System.out.println("用户拿到第"+this.milk+"瓶奶");
}
}
奶箱类 定义了一个milk公共变量 用于统计当前是第几瓶奶
提供了插入方法 put 可以改变milk的值
获取方法 get 可以实时获取当前是第几瓶奶
producer 生成者类 参考代码如下
public class producer implements Runnable {
milkBox ma;
public producer(milkBox ma) {
this.ma = ma;
}
public void run (){
for(int i = 1;i < 6;i++){
ma.put(i);
}
}
}
这里 我们通过带参构造方法 获取了milkBox奶箱类的对象 并存储 实现了Runnable接口 可以实现线程
然后 run 方法中编写逻辑 循环调用5次奶箱类 put插入方法
消费者类 consumer 参考代码如下
public class consumer implements Runnable {
milkBox ma;
public consumer(milkBox ma) {
this.ma = ma;
}
public void run (){
while (true) {
ma.get();
}
}
}
我们消费者类 也利用带参构造方法 获取了milkBox奶箱类的对象 也存储了起来 也实现了 Runnable 接口 说明要实现为一个线程
run 编写一个死循环 去获取 奶箱中的milk变量
text 测试类 参考代码如下
public class text {
public static void main(String args[]) {
milkBox ma = new milkBox();
producer pre = new producer(ma);
consumer cons = new consumer(ma);
Thread p = new Thread(pre);
Thread c = new Thread(cons);
p.start();
c.start();
}
}
我们测试类 通过main 先实例化了 milkBox 奶箱类 然后实例化producer 生产者类 在实例化时 通过构造方法 将milkBox 奶箱类的对象传给了生产者类 下面对consumer消费者类的实例化也是同理
然后通过Thread将生产者 和 消费者类都实例化成了线程
最后调用 start 方法 启动线程
然后我们执行代码
因为 我们消费者类里写的是个死循环 所有 运行一段时间 要赶紧停掉
但把记录翻到最上面 好像用户一直在拿第五瓶奶
这是因为 生产者方法 执行的太快了
我们需要改造一下奶箱类里的两个数据处理方法
将 milkBox 类代码修改如下
public class milkBox {
private int milk;
private boolean stock;
public synchronized void put (int milk){
if(stock) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.milk = milk;
System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱");
stock = true;
}
public synchronized void get(){
if(!stock) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("用户拿到第"+this.milk+"瓶奶");
stock = false;
}
}
首先 我们定义了一个布尔类型的变量 stock 监听奶箱里还有没有牛奶没被消费
然后 把插入 put方法 改成同步方法 因为只有这样才能用锁 然后 判断 stock如果为true 所有还没没有被消费的牛奶 那么 他就等待
stock为 false 说明 已经没有没被消费过的牛奶了 这时 我们执行 插入奶数量逻辑 执行完之后 把stock赋值为 true 告诉系统 我们新加的牛奶还没被消费过
同时 get 消费方法也被上了锁 如果 stock为 false 所有 牛奶都被消费过 我们进入等待 然后
stock为true 说明 还有牛奶没被消费 这时我们执行消费牛奶逻辑 结束后将stock改为 false 说明 牛奶都被消费过了
然后我们运行代码 效果如下
但这时 显然卡死了 就执行了一次 因为我们暂时只有锁定 但没有唤醒操作
将 milkBox 代码更改如下
public class milkBox {
private int milk;
private boolean stock;
public synchronized void put (int milk){
if(stock) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.milk = milk;
System.out.println("送奶工将第"+this.milk+"瓶奶放入奶箱");
stock = true;
notifyAll();
}
public synchronized void get(){
if(!stock) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("用户拿到第"+this.milk+"瓶奶");
stock = false;
notifyAll();
}
}
我们每次 同步方法更改状态后 执行一次notifyAll 唤醒其他的线程
这样我们运行代码如下
就没有任何问题了