一、Condition的使用
ReentrantLock可以实现等待通知模式,但是需要借助Condition 对象
,使用Condition有更好的灵活性,比如实现多路通知功能,也就是在一个Lock
对象里面可以创建多个Condition(对象监视器)实例,线程对象可以注册
在指定的Condition中,从而可以选择性的进行线程通知,在调度线程上更加灵活
在使用wait ,totify进行通知时,被通知的线程由JVM随机选择的。
Synchronized 就相当于整个Lock对象中只有一个Condition对象,所有线程
都注册在它一个对象的身上。线程notifyAll时,没有效率,
需要通知所有的waiting线程,这会出现相当大的效率问题。
package com.it.po.thread11; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Service3 { private ReentrantLock lock =new ReentrantLock(); private Condition condition=lock.newCondition(); public void methodA(){ try { System.out.println("condition begin..."); condition.await(); System.out.println("condition end..."); } catch (InterruptedException e) { e.printStackTrace(); } } }
package com.it.po.thread11; public class MyThread3 extends Thread { private Service3 service3; public MyThread3(Service3 service3) { this.service3 = service3; } @Override public void run() { super.run(); service3.methodA(); } }
package com.it.po.thread11; import com.it.po.thread07.MyService3; public class Run3 { public static void main(String[] args) throws InterruptedException { Service3 myService = new Service3(); MyThread3 my1 = new MyThread3(myService); my1.start(); } }
condition begin... Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.util.concurrent.locks.ReentrantLock$Sync.tryRelease(ReentrantLock.java:151) at java.util.concurrent.locks.AbstractQueuedSynchronizer.release(AbstractQueuedSynchronizer.java:1261) at java.util.concurrent.locks.AbstractQueuedSynchronizer.fullyRelease(AbstractQueuedSynchronizer.java:1723) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2036) at com.it.po.thread11.Service3.methodA(Service3.java:14) at com.it.po.thread11.MyThread3.run(MyThread3.java:10)
缺乏监视器。
package com.it.po.thread11; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Service3 { private ReentrantLock lock =new ReentrantLock(); private Condition condition=lock.newCondition(); public void methodA(){ try { lock.lock(); System.out.println("condition begin..."); condition.await(); System.out.println("condition end..."); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); } } }

condition begin...
二、Condition实现等待、通知。
package com.it.po.thread11; import org.omg.PortableInterceptor.SYSTEM_EXCEPTION; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Service4 { private ReentrantLock lock =new ReentrantLock(); private Condition condition=lock.newCondition(); public void methodA(){ try { lock.lock(); System.out.println("methodA begin time= "+System.currentTimeMillis()); condition.await(); System.out.println("methodA end time= "+System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); System.out.println("methodA 释放锁了。。。"); } } public void methodB(){ try { lock.lock(); System.out.println("methodB begin time= "+System.currentTimeMillis()); condition.signal(); System.out.println("methodB end time= "+System.currentTimeMillis()); }finally { lock.unlock(); System.out.println("methodB 释放锁了。。。"); } } }
package com.it.po.thread11; public class MyThread4 extends Thread { private Service4 service4; public MyThread4(Service4 service4) { this.service4 = service4; } @Override public void run() { super.run(); service4.methodA(); } }
package com.it.po.thread11; public class Run4 { public static void main(String[] args) throws InterruptedException { Service4 myService = new Service4(); MyThread4 my1 = new MyThread4(myService); my1.start(); Thread.sleep(3000); myService.methodB(); } }
methodA begin time= 1575556005791 methodB begin time= 1575556008790 methodB end time= 1575556008790 methodB 释放锁了。。。 methodA end time= 1575556008790 methodA 释放锁了。。。
实现等待、通知
总结:
1)Object 的wait() 相当于Condition的await()
2) Object 的wait(long timeOut) 相当于Condition的 await(long time, TimeUnit unit)
3) Object 的notify相当于Contition的signal()
4) Object 的notifyAll相当于Contition的signalAll()
三、使用多个Condition实现等待、通知。
(一)错误的使用方式
package com.it.po.thread11; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Service5 { private ReentrantLock lock =new ReentrantLock(); private Condition condition=lock.newCondition(); public void methodA(){ try { lock.lock(); System.out.println("methodA begin time= "+System.currentTimeMillis()); condition.await(); System.out.println("methodA end time= "+System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); System.out.println("methodA 释放锁了。。。"); } } public void methodB(){ try { lock.lock(); System.out.println("methodB begin time= "+System.currentTimeMillis()); condition.await(); System.out.println("methodB end time= "+System.currentTimeMillis()); }catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println("methodB 释放锁了。。。"); } } public void methodC(){ try { lock.lock(); System.out.println("methodC begin time= "+System.currentTimeMillis()); condition.signal(); Thread.sleep(1000); System.out.println("methodC end time= "+System.currentTimeMillis()); }catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println("methodC 释放锁了。。。"); } } }

package com.it.po.thread11; import com.it.po.thread10.MyThread5; public class Run5 { public static void main(String[] args) throws InterruptedException { Service5 myService = new Service5(); MyThread5_1 my1 = new MyThread5_1(myService); MyThread5_2 my2 = new MyThread5_2(myService); my1.start(); my2.start(); Thread.sleep(2000); myService.methodC(); } }

methodA begin time= 1575557073312 methodB begin time= 1575557073315 methodC begin time= 1575557075312 methodC end time= 1575557076312 methodC 释放锁了。。。 methodA end time= 1575557076312 methodA 释放锁了。。。
B线程继续等。。。
(二)错误的使用方式
package com.it.po.thread11; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Service5 { private ReentrantLock lock =new ReentrantLock(); private Condition condition=lock.newCondition(); public void methodA(){ try { lock.lock(); System.out.println("methodA begin time= "+System.currentTimeMillis()); condition.await(); System.out.println("methodA end time= "+System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); System.out.println("methodA 释放锁了。。。"); } } public void methodB(){ try { lock.lock(); System.out.println("methodB begin time= "+System.currentTimeMillis()); condition.await(); System.out.println("methodB end time= "+System.currentTimeMillis()); }catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println("methodB 释放锁了。。。"); } } public void methodC(){ try { lock.lock(); System.out.println("methodC begin time= "+System.currentTimeMillis()); condition.signalAll(); Thread.sleep(1000); System.out.println("methodC end time= "+System.currentTimeMillis()); }catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println("methodC 释放锁了。。。"); } } }
methodB begin time= 1575557358266 methodA begin time= 1575557358268 methodC begin time= 1575557360265 methodC end time= 1575557361265 methodC 释放锁了。。。 methodB end time= 1575557361265 methodB 释放锁了。。。 methodA end time= 1575557361265 methodA 释放锁了。。。
ok全部释放锁了,如果想单独唤醒一部分的线程怎么办呢?
这就有必要创建多个Condition了,就是Contition对象
可以唤醒部分线程,有助于提高程序的运行效率,可以先对线程
进行分组,再唤醒指定的组中的线程。
(三)使用多个Condition的正确的使用方式
package com.it.po.thread11; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class Service6 { private ReentrantLock lock =new ReentrantLock(); private Condition condition1=lock.newCondition(); private Condition condition2=lock.newCondition(); public void methodA(){ try { lock.lock(); System.out.println("methodA begin time= "+System.currentTimeMillis()); condition1.await(); System.out.println("methodA end time= "+System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); }finally { lock.unlock(); System.out.println("methodA 释放锁了。。。"); } } public void methodB(){ try { lock.lock(); System.out.println("methodB begin time= "+System.currentTimeMillis()); condition1.await(); System.out.println("methodB end time= "+System.currentTimeMillis()); }catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println("methodB 释放锁了。。。"); } } public void methodC(){ try { lock.lock(); System.out.println("methodC begin time= "+System.currentTimeMillis()); condition2.await(); System.out.println("methodC end time= "+System.currentTimeMillis()); }catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); System.out.println("methodC 释放锁了。。。"); } } public void methodD(){ try { lock.lock(); System.out.println("methodD begin time= "+System.currentTimeMillis()); condition1.signalAll(); System.out.println("methodD end time= "+System.currentTimeMillis()); } finally { lock.unlock(); System.out.println("methodD 释放锁了。。。"); } } }

package com.it.po.thread11; public class Run6 { public static void main(String[] args) throws InterruptedException { Service6 myService = new Service6(); MyThread6_1 my1 = new MyThread6_1(myService); MyThread6_2 my2 = new MyThread6_2(myService); MyThread6_3 my3 = new MyThread6_3(myService); my1.start(); my2.start(); my3.start(); Thread.sleep(2000); myService.methodD(); } }

methodA begin time= 1575557916439 methodC begin time= 1575557916439 methodB begin time= 1575557916440 methodD begin time= 1575557918439 methodD end time= 1575557918439 methodD 释放锁了。。。 methodA end time= 1575557918439 methodA 释放锁了。。。 methodB end time= 1575557918439 methodB 释放锁了。。。
线程AB是被Condition1锁住的,可以释放。
由此达到了唤醒指定线程的作用。
浙公网安备 33010602011771号