Condition是在java1.5才出现。它用来替换传统的 wait(), notify()实现线程之间的协作。但是更加强大。
Condition用 await(), signal, signalAll方法替代wait(), notify()。假如用wait,notify,有三个线程调用一个对象的某个方法,notify只能随机的唤醒一个线程,而不能指定唤醒某个线程,但是用condition的话,就可以唤醒指定的线程。可以看下面的例子。
condition的await,signal和 wait,notify都需要在锁之间运行。
contidion也被用来实现阻塞队列。
condition是通过锁创建出来的。基本代码是 ReentrantLock.newCondition().
lock.lock();
condition.await();
lock.unlock();
下面实现一个 一直abc abc这么有顺序的执行。
下面用synchronized , wait ,notify来实现。
总共有四个类。DemoNoCondition, A,B,C. 其中DemoNoCondition内部有三个方法,a,b,c,都加上了锁,用来打印abc的。A B C三个类,用来表示多个线程调用DemoNoCondition的几个方法来打印abc
package com.citi.test.mutiplethread.demo5; public class DemoNoCondition { private int signal; public synchronized void a(){ while(signal!=0){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("a"+signal); signal++; notifyAll(); } public synchronized void b(){ while(signal!=1){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("b"+signal); signal++; notifyAll(); } public synchronized void c(){ while(signal!=2){ try { wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("c"+signal); signal=0; notifyAll(); } public static void main(String[] args) { DemoNoCondition d=new DemoNoCondition(); A a=new A(d); B b=new B(d); C c=new C(d); new Thread(a).start(); new Thread(a).start(); new Thread(a).start(); new Thread(a).start(); new Thread(c).start(); new Thread(c).start(); new Thread(c).start(); new Thread(c).start(); new Thread(b).start(); new Thread(b).start(); new Thread(b).start(); new Thread(b).start(); new Thread(b).start(); } }
package com.citi.test.mutiplethread.demo5; public class A implements Runnable{ private DemoNoCondition demoCondition; public A(DemoNoCondition demo) { this.demoCondition=demo; } @Override public void run() { while(true){ demoCondition.a(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
package com.citi.test.mutiplethread.demo5; public class B implements Runnable { private DemoNoCondition demoCondition; public B(DemoNoCondition demoCondition) { this.demoCondition=demoCondition; } @Override public void run() { while(true){ demoCondition.b(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
package com.citi.test.mutiplethread.demo5; public class C implements Runnable { private DemoNoCondition demoCondition; public C(DemoNoCondition demoCondition) { this.demoCondition=demoCondition; } @Override public void run() { while(true){ demoCondition.c(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
下面是输出结果。
下面来看看用condition来实现这个功能。代码其实是类似的,只不过,用condition,可以指定唤醒某个线程。可以对比一下两个实现的代码,一个是用notifyAll,一个是直接指定
c.signal,来通知线程c唤醒。这个就是condition的强大之处。
package com.citi.test.mutiplethread.demo5; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class DemoCondition { private int signal; private Lock lock=new ReentrantLock(); private Condition a=lock.newCondition(); private Condition b=lock.newCondition(); private Condition c=lock.newCondition(); public void a(){ lock.lock(); while(signal!=0){ try { a.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("a"+signal); signal++; b.signal(); lock.unlock(); } public void b(){ lock.lock(); while(signal!=1){ try { b.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("b"+signal); signal++; c.signal(); lock.unlock(); } public void c(){ lock.lock(); while(signal!=2){ try { c.await(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println("c"+signal); signal=0; a.signal(); lock.unlock(); } public static void main(String[] args) { DemoCondition condition=new DemoCondition(); ACondition a=new ACondition(condition); BCondition b=new BCondition(condition); CCondition c=new CCondition(condition); new Thread(b).start(); new Thread(a).start(); new Thread(a).start(); new Thread(b).start(); new Thread(c).start(); new Thread(a).start(); new Thread(c).start(); new Thread(a).start(); new Thread(c).start(); new Thread(c).start(); } }
package com.citi.test.mutiplethread.demo5; public class ACondition implements Runnable { private DemoCondition condition; public ACondition(DemoCondition condition) { this.condition=condition; } @Override public void run() { while(true){ condition.a(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
package com.citi.test.mutiplethread.demo5; public class BCondition implements Runnable { private DemoCondition condition; public BCondition(DemoCondition condition) { this.condition = condition; } public void run() { while(true){ condition.b(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; }
package com.citi.test.mutiplethread.demo5; public class CCondition implements Runnable { private DemoCondition condition; public CCondition(DemoCondition condition) { this.condition = condition; } @Override public void run() { while(true){ condition.c(); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }