本文共 3216 字,大约阅读时间需要 10 分钟。
通常在开发并发程序的时候,会碰到需要停止正在执行业务A,来执行另一个业务B,当业务B执行完成后业务A继续执行。ReentrantLock通过Condtion等待/唤醒这样的机制.
相比较synchronize的wait()和notify()/notifAll()的机制而言,Condition具有更高的灵活性,这个很关键。Conditon可以实现多路通知和选择性通知。
当使用notify()/notifAll()时,JVM时随机通知线程的,具有很大的不可控性,所以建议使用Condition。
package com.caojiulu;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;/** * *@author caojiulu * *类说明: */public class ExpressCond { public final static String CITY = "ShangHai"; private int km;/*快递运输里程数*/ private String site;/*快递到达地点*/ private Lock lock = new ReentrantLock(); private Condition keCond = lock.newCondition(); private Condition siteCond = lock.newCondition(); public ExpressCond() { } public ExpressCond(int km, String site) { this.km = km; this.site = site; } /* 变化公里数,然后通知处于wait状态并需要处理公里数的线程进行业务处理*/ public void changeKm(){ lock.lock(); try { this.km = 101; keCond.signalAll(); }finally { lock.unlock(); } } /* 变化地点,然后通知处于wait状态并需要处理地点的线程进行业务处理*/ public void changeSite(){ lock.lock(); try { this.site = "BeiJing"; siteCond.signal(); }finally { lock.unlock(); } } /*当快递的里程数大于100时更新数据库*/ public void waitKm(){ lock.lock(); try { while(this.km<=100) { try { keCond.await(); System.out.println("check km thread["+Thread.currentThread().getId() +"] is be notifed."); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }finally { lock.unlock(); } System.out.println("the Km is "+this.km+",I will change db"); } /*当快递到达目的地时通知用户*/ public void waitSite(){ lock.lock(); try { while(CITY.equals(this.site)) { try { siteCond.await(); System.out.println("check site thread["+Thread.currentThread().getId() +"] is be notifed."); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }finally { lock.unlock(); } System.out.println("the site is "+this.site+",I will call user"); }}
测试类:
package com.caojiulu;/** *@author caojiulu * *类说明:测试Lock和Condition实现等待通知 */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();//快递里程变化 }}
分别实例化了两个Condition对象,都是使用同一个lock注册。注意keCond对象的等待和唤醒只对使用了keCond的线程有用,同理siteCond对象的等待和唤醒只对使用了siteCond的线程有用。
转载地址:http://uayyb.baihongyu.com/