关键字Synchronized与wait()和notify()/notifyAll()方法相结合可以实现等待通知,ReentrantLock借助Condition对象可以实现同样的功能,而且一个lock对象可以创建多个condition对象,从而能够选择性condition对象进行等待/通知
condition对象实现等待通知的简单案例
public class ConditionLockDemo { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition(); public void csleep(){ try{ lock.lock(); System.out.println(Thread.currentThread().getName()+"current time :"+System.currentTimeMillis()); condition.await(); System.out.println(Thread.currentThread().getName()+"唤醒后 current time :"+System.currentTimeMillis()); } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } public void signal(){ try{ lock.lock(); condition.signal(); }finally{ lock.unlock(); } } }
启动两个线程,分别调用两个方法
public static void main(String[] args) throws InterruptedException { final ConditionLockDemo cl = new ConditionLockDemo(); Thread a = new Thread(new Runnable() { @Override public void run() { cl.csleep(); } }, "A"); Thread b = new Thread(new Runnable() { @Override public void run() { cl.signal(); } }, "B"); a.start(); Thread.sleep(1000); b.start(); }
输出:
Acurrent time :1525329885799 A唤醒后 current time :1525329886799
从这个简单案例:
* condition 对象是lock对象进行创建的,而且一个lock对象可以创建多个condition对象
* 等待通知的实现,借助condition 对象的await()方法进入阻塞状态释放锁,signal方法唤醒waiting的线程
* await()和signal方法的调用必须都要先在获取到锁之后(lock.lock())
方法 | 描述 |
await() | 当前线程进入waiting状态,并且释放当前线程的锁,当前线程被唤醒,直到其他线程调用signal、signalAll或者interrupt方法 如果线程从await方法返回,表示已经获取到锁 |
awaitUninterruptibly() | 和上面方法一致,区别在于对于其他线程的中断方法不敏感 |
awaitUntil(Date deadline) | 当前线程进入等待状态直到被通知、中断或者到某个时间点,如果没有到时间点就被通知,方法返回true,否则到了指定时间,返回false |
signal() | 获取到锁后,唤醒处于waiting状态的线程 |
signalAll() | 获取到锁后,唤醒所有处在waiting状态的线程 |
condition实现生产者消费者模型
3个线程轮流打印1,2,3 。。。
思想:
3个线程,创建3个condition对象
3个线程读取同一个共享变量的值,然后根据值,判断是否进入阻塞状态
,如果不是阻塞状态,修改这个值,并唤醒下一个线程, A-B-C-A轮流唤醒
public class ThreeConditionDemo { private Lock lock = new ReentrantLock(); private Condition condition1 = lock.newCondition(); private Condition condition2 = lock.newCondition(); private Condition condition3 = lock.newCondition(); private volatile int count = 1; public void printA() { try{ lock.lock(); while(count!=1){ condition1.await(); } Thread.sleep(1000); System.out.println("1"); count = 2 ; condition2.signal(); } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } public void printB(){ try{ lock.lock(); while(count!=2){ condition2.await(); } Thread.sleep(1000); System.out.println("2"); count = 3; condition3.signal(); } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } public void printC(){ try{ lock.lock(); while(count!=3){ condition3.await(); } Thread.sleep(1000); System.out.println("3"); count = 1; condition1.signal(); } catch (InterruptedException e) { e.printStackTrace(); }finally{ lock.unlock(); } } }
启动三个线程测试:
public static void main(String[] args) { final ThreeConditionDemo tcd = new ThreeConditionDemo(); Thread t1 = new Thread(new Runnable() { @Override public void run() { while(true){ tcd.printA(); } } }); Thread t2 = new Thread(new Runnable() { @Override public void run() { while(true){ tcd.printB(); } } }); Thread t3 = new Thread(new Runnable() { @Override public void run() { while(true){ tcd.printC(); } } }); t1.start(); t2.start(); t3.start(); }Object监视器锁和Condition方法的对比
对比项 | Object监视器方法 | Condition |
前置条件 | 获取object对象的锁 | 调用lock.lock()获取锁 |
调用方法 | object.wait/notify,notifyAll | Condition condition = lock.newCondition() condition.await/signal,signalAll |
释放锁进入等待状态,能够不响应中断 | 不支持 | 支持 |
释放锁进入超时等待 | 支持 | 支持 |
等待队列的个数 | 1个 | 多个,lock可以创建多个condition,调用一个condition.await方法 就加入等待队列中 |