Concurrency Utilities 并发处理(2)Condition 条件变量

来源:互联网 发布:ip与mac绑定 编辑:程序博客网 时间:2024/06/06 02:19
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.");   }  } }}程序运行结果如下:Tue Jan 24 14:42:31 CST 2006 W Thread[Thread-0,5,main] wait for event.Tue Jan 24 14:42:31 CST 2006 W Thread[Thread-2,5,main] wait for event.Tue Jan 24 14:42:31 CST 2006 W Thread[Thread-1,5,main] wait for event.Tue Jan 24 14:42:31 CST 2006 N Thread[Thread-3,5,main] fire event.Tue Jan 24 14:42:31 CST 2006 W Thread[Thread-0,5,main] got event.Tue Jan 24 14:42:32 CST 2006 N Thread[Thread-3,5,main] fire event.Tue Jan 24 14:42:32 CST 2006 W Thread[Thread-2,5,main] got event.Tue Jan 24 14:42:33 CST 2006 N Thread[Thread-3,5,main] fire event.Tue Jan 24 14:42:33 CST 2006 W Thread[Thread-1,5,main] got event.Tue Jan 24 14:42:34 CST 2006 N Thread[Thread-3,5,main] fire event.Tue Jan 24 14:42:34 CST 2006 W Thread[Thread-0,5,main] got event.Tue Jan 24 14:42:36 CST 2006 N Thread[Thread-3,5,main] fire event.Tue Jan 24 14:42:36 CST 2006 W Thread[Thread-2,5,main] got event.前三行启动3个等候线程,线程阻塞在 event.wait()上。第四行通知线程Thread-3,调用event.notify(); 第五行Thread-0线程,got event.一秒钟后,Thread-3,又触发了event.notify();下面将NotifyThread中的 event.notify(); 改为event.notifyAll(); 看一下运行结果:Tue Jan 24 15:25:43 CST 2006 W Thread[Thread-1,5,main] wait for event.Tue Jan 24 15:25:43 CST 2006 W Thread[Thread-2,5,main] wait for event.Tue Jan 24 15:25:43 CST 2006 W Thread[Thread-0,5,main] wait for event.Tue Jan 24 15:25:44 CST 2006 N Thread[Thread-3,5,main] fire event.Tue Jan 24 15:25:44 CST 2006 W Thread[Thread-1,5,main] got event.Tue Jan 24 15:25:44 CST 2006 W Thread[Thread-0,5,main] got event.Tue Jan 24 15:25:44 CST 2006 W Thread[Thread-2,5,main] got event.Tue Jan 24 15:25:45 CST 2006 N Thread[Thread-3,5,main] fire event.Tue Jan 24 15:25:45 CST 2006 W Thread[Thread-0,5,main] got event.Tue Jan 24 15:25:45 CST 2006 W Thread[Thread-1,5,main] got event.Tue Jan 24 15:25:45 CST 2006 W Thread[Thread-2,5,main] got event.Tue Jan 24 15:25:46 CST 2006 N Thread[Thread-3,5,main] fire event.Tue Jan 24 15:25:46 CST 2006 W Thread[Thread-1,5,main] got event.Tue Jan 24 15:25:46 CST 2006 W Thread[Thread-0,5,main] got event.Tue Jan 24 15:25:46 CST 2006 W Thread[Thread-2,5,main] got event.可以看到当Thread-3,event.notifyAll(); 所有的线程都 got 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.

原创粉丝点击