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(); } } } }