Condition 条件变量
条件变量是线程同步对象中的一种,主要用来等待某种条件的发生,条件发生后,可以唤醒等待在该条件上的一个线程,或所有线程。条件变量要与锁一起协同工作.
条件变量调用Lock.newCondition()获得一个实例:
ReentrantLock lock = new ReentrantLock();
Condition condition =
lock.newCondition();
通常的调用方式如下:
// 当条件 con == true 时等待 lock.lock(); try { if (con == true) { condition.await(); } // do something } finally { lock.unlock(); }
// 条件变量的唤醒:
condition.signal(); //唤醒等待的其中一个线程
condition.signalAll(); //唤醒等待的所有线程
条件变量类似JDK1.4或以前版本中的 Object.wait(); Object.notify(); Object.notifyAll();
值得注意的是当condition.await()时,隐式的将条件变量关联的Lock解锁,而使其他线程有机会获得Lock,而检查条件,并在条件满足时,等待在条件变量上。
我们先来看一下没有条件变量时,传统的处理方式:
下面这个例子,创建3个等候线程,每个线程循环调用event.wait(),
等到了event后,显示相应的信息。
然后创建1个通知线程,每隔1秒调用 event.notify() 通知等待线程。
import java.util.Calendar; public class TestWait { // 创建event Object,以使用它的wait(), notify()等方法 private Object event = null; public TestWait() { // 创建event event = new Object(); } public static void main(String[] args) { TestWait tester = new TestWait(); tester.test(); } public Object getEvent() { return event; } public void test() { // 启动3个等候线程 new Thread(new WaitThread(this)).start(); new Thread(new WaitThread(this)).start(); new Thread(new WaitThread(this)).start(); // 启动通知线程 new Thread(new NotifyThread(this)).start(); } }
class WaitThread implements Runnable { private TestWait tester = null; public WaitThread(TestWait tester) { this.tester = tester; } public void run() { Calendar now = Calendar.getInstance(); System.out.println(now.getTime() + " W " + Thread.currentThread() + " wait for event."); while (true) { try { // 同步访问 event synchronized (tester.getEvent()) { // 等待在 event 上 tester.getEvent().wait(); } // 等到 event 后,显示信息 "got event" Calendar now1 = Calendar.getInstance(); System.out.println(now1.getTime() + " W " + Thread.currentThread() + " got event."); // do something ... Thread.sleep(500); } catch (Exception e) { e.printStackTrace(); } } } }
class NotifyThread implements Runnable { private TestWait tester = null; public NotifyThread(TestWait tester) { this.tester = tester; } public void run() { while (true) { try { // 间隔1秒 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // 同步访问 event synchronized (tester.getEvent()) { // 通知等在event上的一个线程 tester.getEvent().notify(); // 通知等在event上的所有线程 // tester.getEvent().notifyAll(); // 打印 "fire event" 信息。 Calendar now = Calendar.getInstance(); System.out.println(now.getTime() + " N " + Thread.currentThread() + " fire event."); } } } }
程序运行结果如下:
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class TestCondition { private ReentrantLock lock = null; private Condition condition = null; public TestCondition() { lock = new ReentrantLock(); condition = lock.newCondition(); } public static void main(String[] args) { TestCondition tester = new TestCondition(); tester.test(); } public void test() { new Thread(new WaitThread1(this)).start(); new Thread(new WaitThread1(this)).start(); new Thread(new WaitThread1(this)).start(); new Thread(new NotifyThread1(this)).start(); } public ReentrantLock getLock() { return lock; } public Condition getCondition() { return condition; } }
class NotifyThread1 implements Runnable { private TestCondition tester = null; public NotifyThread1(TestCondition tester) { this.tester = tester; } public void run() { while (true) { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } tester.getLock().lock(); tester.getCondition().signal(); System.out.println(Thread.currentThread() + " condition signal."); tester.getLock().unlock(); } } }
class WaitThread1 implements Runnable { private TestCondition tester = null; public WaitThread1(TestCondition tester) { this.tester = tester; } public void run() { System.out.println(Thread.currentThread() + " started."); while (true) { tester.getLock().lock(); try { // getCondition().await() 将使getLock()解锁,以便其他线程可以进入 await(); tester.getCondition().await(); System.out.println(Thread.currentThread() + " get condition."); } catch (InterruptedException e) { e.printStackTrace(); } finally { tester.getLock().unlock(); } } } }运行结果如下:
Thread[Thread-0,5,main] started.
Thread[Thread-1,5,main] started.
Thread[Thread-2,5,main] started.
Thread[Thread-3,5,main] condition
signal.
Thread[Thread-0,5,main] get condition.
Thread[Thread-3,5,main]
condition signal.
Thread[Thread-1,5,main] get condition.
Thread[Thread-3,5,main] condition signal.
Thread[Thread-2,5,main] get
condition.
Thread[Thread-3,5,main] condition signal.
Thread[Thread-0,5,main] get condition.