Condition将Object监视器方法(wait、notify和notifyAll)分解成截然不同的对象,以便通过将这些对象与任意Lock实现组合使用,为每个对象提供多个等待set(wait-set)。其中,Lock替代了synchronized方法和语句的使用,Condition替代了Object监视器方法的使用。
Condition(也称为条件队列或条件变量)为线程提供了一个含义,以便在某个状态条件现在可能为true的另一个线程通知它之前,一直挂起该线程(即让其“等待”)。因为访问此共享状态信息发生在不同的线程中,所以它必须受保护,因此要将某种形式的锁与该条件相关联。等待提供一个条件的主要属性是:以原子方式释放相关的锁,并挂起当前线程,就像Object.wait做的那样。
Condition
实例实质上被绑定到一个锁上。要为特定 Lock
实例获得 Condition
实例,请使用其 newCondition()
方法。
Condition | Object |
void await() 造成当前线程在接到信号或被中断之前一直处于等待状态。 | void wait() 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 |
boolean await(long time, TimeUnit unit) 造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。 | void wait(long timeout) 在其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量前,导致当前线程等待。 |
void signal() 唤醒一个等待线程。 | void notify() 唤醒在此对象监视器上等待的单个线程 |
void signalAll() 唤醒所有等待线程。 | void notifyAll() 唤醒在此对象监视器上等待的所有线程。 |
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; public class ConditionDemo { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void method1(){ try { lock.lock(); System.out.println("当前线程:" + Thread.currentThread().getName() + "进入method1.."); Thread.sleep(3000); System.out.println("当前线程:" + Thread.currentThread().getName() + "进入等待状态,并释放锁.."); condition.await(); //await释放锁 Object wait System.out.println("当前线程:" + Thread.currentThread().getName() +"继续执行..."); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void method2(){ try { lock.lock(); System.out.println("当前线程:" + Thread.currentThread().getName() + "进入method2.."); Thread.sleep(3000); System.out.println("当前线程:" + Thread.currentThread().getName() + " 唤醒t1线程 .."); condition.signal(); //唤醒一个等待线程 Object notify } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public static void main(String[] args) { final ConditionDemo uc = new ConditionDemo(); Thread t1 = new Thread(new Runnable() { @Override public void run() { uc.method1(); } }, "t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { uc.method2(); } }, "t2"); t1.start(); t2.start(); } }
当前线程:t1进入method1..
当前线程:t1进入等待状态,并释放锁..
当前线程:t2进入method2..
当前线程:t2 唤醒t1线程 ..
当前线程:t1继续执行...
多个Condition
import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; public class ManyCondition { private ReentrantLock lock = new ReentrantLock(); private Condition c1 = lock.newCondition(); private Condition c2 = lock.newCondition(); public void m1(){ try { lock.lock(); System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m1等待.."); c1.await(); System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m1继续.."); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void m2(){ try { lock.lock(); System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m2等待.."); c1.await(); System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m2继续.."); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void m3(){ try { lock.lock(); System.out.println("当前线程:" +Thread.currentThread().getName() + "进入方法m3等待.."); c2.await(); System.out.println("当前线程:" +Thread.currentThread().getName() + "方法m3继续.."); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void m4(){ try { lock.lock(); System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒.."); c1.signalAll(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public void m5(){ try { lock.lock(); System.out.println("当前线程:" +Thread.currentThread().getName() + "唤醒.."); c2.signal(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } public static void main(String[] args) throws Exception { ManyCondition umc = new ManyCondition(); Thread t1 = new Thread(new Runnable() { @Override public void run() { umc.m1();} },"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { umc.m2();} },"t2"); Thread t3 = new Thread(new Runnable() { @Override public void run() { umc.m3();} },"t3"); Thread t4 = new Thread(new Runnable() { @Override public void run() { umc.m4();} },"t4"); Thread t5 = new Thread(new Runnable() { @Override public void run() { umc.m5();} },"t5"); t1.start(); // c1 t2.start(); // c1 t3.start(); // c2 Thread.sleep(2000); t4.start(); // c1 Thread.sleep(2000); t5.start(); // c2 } }
当前线程:t1进入方法m1等待..
当前线程:t2进入方法m2等待..
当前线程:t3进入方法m3等待..
当前线程:t4唤醒..
当前线程:t1方法m1继续..
当前线程:t2方法m2继续..
当前线程:t5唤醒..
当前线程:t3方法m3继续..