关于JAVA Condition 条件变量

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.

 

你可能感兴趣的:(关于JAVA Condition 条件变量)