关键字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方法 就加入等待队列中 |