接上一篇,上篇讲到使用wait跟notify方法再配合synchronized关键字实现线程间的通讯。本篇讲解JDK1.5之后提供另外一套通讯机制。实现原理一致,区别仅仅操作方式而已。
延续上篇的需求:
需求: 一个包子店, 只有一个面包师, 一个蒸笼.蒸笼只能放满10个包子, 当满10个包子时,面包师可以休息.如果包子卖完了,就得开始弄包子.而顾客一次买一个包子, 当包子就只能等啦.
package cn.wolfcode.ch11;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class BaoZiShop {
//包子个数
private int baoziNum = 0;
//获取重入锁
private ReentrantLock lock = new ReentrantLock();
//通过重入锁获取锁绑定状态(条件)实例
//该对象可以实现等同object中的wait跟notify功能
private Condition condition = lock.newCondition();
public int getBaoziNum() {
return baoziNum;
}
public void setBaoziNum(int baoziNum) {
this.baoziNum = baoziNum;
}
public ReentrantLock getLock() {
return lock;
}
public Condition getCondition() {
return condition;
}
}
package cn.wolfcode.ch11;
//面包师
public class Baker {
private BaoZiShop shop;
public Baker(BaoZiShop shop) {
this.shop = shop;
}
public void product() {
while (true) {
//获取锁
shop.getLock().lock();
try {
if (shop.getBaoziNum() >= 10) {
try {
System.out.println("面包师:" + Thread.currentThread().getName()
+ "发现包子满了,果断休息...");
shop.getCondition().await();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
shop.setBaoziNum(shop.getBaoziNum() + 1);
System.out.println("面包师:" + Thread.currentThread().getName()
+ "生产了1个包子, 还有" + shop.getBaoziNum() + "个包子");
shop.getCondition().signal(); //通知顾客, 可以买包子了
}
} finally {
shop.getLock().unlock();
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package cn.wolfcode.ch11;
//顾客
public class Customer {
private BaoZiShop shop;
public Customer(BaoZiShop shop) {
this.shop = shop;
}
public void buy() {
while (true) {
shop.getLock().lock();
try {
if (shop.getBaoziNum() <= 0) {
try {
System.out.println("顾客:" + Thread.currentThread().getName()
+ "发现没包子了, 通知老板弄包子, 在等待...");
shop.getCondition().await();
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
shop.setBaoziNum(shop.getBaoziNum() - 1);
System.out.println("顾客:" + Thread.currentThread().getName() +
" 买了1包子, 还有" + shop.getBaoziNum() + "个包子");
shop.getCondition().signal(); //客户急,催老板赶紧弄
}
} finally {
shop.getLock().unlock();
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
package cn.wolfcode.ch11;
import cn.wolfcode.ch10.Resource;
public class App {
public static void main(String[] args) {
//同一个包子店
BaoZiShop shop = new BaoZiShop();
//面包师
final Baker baker = new Baker(shop);
new Thread(new Runnable() {
public void run() {
baker.product();;
}
}, "baker1").start(); //一个面包师
//顾客
final Customer customer = new Customer(shop);
new Thread(new Runnable() {
public void run() {
customer.buy();
}
}, "customer1").start(); //一个顾客
}
}
结果跟上篇操作结果一样。
注意点:
1>BaoZiShop 类多了2个属性:
//获取重入锁
private ReentrantLock lock = new ReentrantLock();
用于替换:synchronized 关键字,具体看Baker类
//通过重入锁获取锁绑定状态(条件)实例
private Condition condition = lock.newCondition();
用来替换锁对象的wait跟notify方法
shop.wait() ——-> 等价于: condition.await();
shop.notify() ———>等价于:condition.signal();
shop.notifyAll() ———>等价于:condition.signalAll();
2>Condition 类可以翻译成类锁条件/锁状态, 需要跟lock配套使用
public interface Condition {
//将当前线程加入等待队列,同时释放与Object.wait()类似。
void await() throws InterruptedException;
//与await()基本一致,唯一不同点在于,指定时间之内没有收到signal()或
//signalALL()信号或者线程中断时该方法会返回false;其它情况返回true。
boolean await(long time, TimeUnit unit) throws InterruptedException;
//唤醒一个在 await()等待队列中的线程。与Object.notify()相似
void signal();
//唤醒 await()等待队列中所有的线程。与object.notifyAll()相似
void signalAll();
.....
}
本篇到此结束,condition类具体解析下回再分解。