今天我们分析并发编程原子操作 AQS 思想之Condition 接口 的标准使用:
任意一个 Java 对象,都拥有一组监视器方法(定义在 java.lang.Object 上), 主要包括 wait()、wait(long timeout)、notify()以及 notifyAll()方法,这些方法与
synchronized
同步关键字配合,可以实现等待
/
通知模式。
Condition
接口也提供 了类似 Object
的监视器方法,与
Lock
配合可以实现等待
/
通知模式。
1、Condition
常用方法:
2、Condition
使用范式:
3、Condition
使用 配合Lock接口:
public class ExpressCond {
public final static String CITY = "ShangHai";
private int km;/*快递运输里程数*/
private String site;/*快递到达地点*/
private Lock kmLock = new ReentrantLock();//里程锁
private Lock siteLock = new ReentrantLock();//地点锁,可以和里程锁用同意把锁。
private Condition kmCond = kmLock.newCondition();//控制里程数的
private Condition siteCond = siteLock.newCondition();//控制地点的
public ExpressCond() {
}
public ExpressCond(int km, String site) {
this.km = km;
this.site = site;
}
/* 变化公里数,然后通知处于wait状态并需要处理公里数的线程进行业务处理*/
public void changeKm(){
kmLock.lock();
try{
this.km = 101;
kmCond.signal();
//kmCond.signalAll();
}finally {
kmLock.unlock();
}
}
/* 变化地点,然后通知处于wait状态并需要处理地点的线程进行业务处理*/
public void changeSite(){
siteLock.lock();
try {
this.site = "BeiJing";
siteCond.signal();//通知其他在锁上等待的线程
}finally {
siteLock.unlock();
}
}
/*当快递的里程数大于100时更新数据库*/
public void waitKm(){
kmLock.lock();
try{
while(this.km<100){
try {
kmCond.await();
System.out.println("Check Site thread["
+Thread.currentThread().getId()
+"] is be notified");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}finally {
kmLock.unlock();
}
System.out.println("the Km is "+this.km+",I will change db");
}
/*当快递到达目的地时通知用户*/
public void waitSite(){
siteLock.lock();
try {
while(this.site.equals(CITY)) {
try {
siteCond.await();//当前线程进行等待
System.out.println("check Site thread["+Thread.currentThread().getName()
+"] is be notify");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}finally {
siteLock.unlock();
}
System.out.println("the site is "+this.site+",I will call user");
}
}
测试main方法:
public class TestCond {
private static ExpressCond express = new ExpressCond(0,ExpressCond.CITY);
/*检查里程数变化的线程,不满足条件,线程一直等待*/
private static class CheckKm extends Thread{
@Override
public void run() {
express.waitKm();
}
}
/*检查地点变化的线程,不满足条件,线程一直等待*/
private static class CheckSite extends Thread{
@Override
public void run() {
express.waitSite();
}
}
public static void main(String[] args) throws InterruptedException {
for(int i=0;i<3;i++){
new CheckSite().start();
}
for(int i=0;i<3;i++){
new CheckKm().start();
}
Thread.sleep(1000);
express.changeKm();//快递里程变化
express.changeSite();//快递地点变化
}
}
执行结果:
4、了解
LockSupport:
LockSupport
定义了一组的公共静态方法,这些方法提供了最基本的线程阻 塞和唤醒功能,而 LockSupport
也成为构建同步组件的基础工具。
LockSupport
定义了一组以
park
开头的方法用来阻塞当前线程,以及 unpark(Thread thread)方法来唤醒一个被阻塞的线程。
LockSupport
增加了 park(Object blocker)、
parkNanos(Object blocker,long nanos)
和
parkUntil(Object blocker,long deadline)3 个方法,用于实现阻塞当前线程的功能,其中参数
blocker 是用来标识当前线程在等待的对象(以下称为阻塞对象),该对象主要用于问题 排查和系统监控,此类用的不多,方法如下图:
有用到时可以认真测试,今天分享到此结束。