Condition介绍
condition用 await(), signal, signalAll方法替代Object 中的 wait(), notify()
condition的await,signal和 wait,notify都需要在锁之间运行
contidion也被用来实现阻塞队列
condition是通过锁创建出来的。基本代码是 ReentrantLock.newCondition()
Condition 的作用
当线程1需要等待某个条件的时候,它就去执行condition.await()方法,一旦执行了await()方法,线程就会进入阻塞状态,然后通常会有另外一个线程,假设是线程2,去执行对应的条件,直到这个条件达成的时候,线程2就会去执行condition.signal()方法,这时JVM就会从被阻塞的线程里找,找到那些等待该condition的线程,当线程1就会收到可执行信号的时候,它的线程状态就会变成Runnable可执行状态 。
signalAll() 和 signal 的区别
signalAll()会唤起所有的正在等待的线程,但是signal0是公平的,只会唤起那个等待时间最长的线程 。
public class ConditionDemo {
public static void main(String[] args) throws InterruptedException {
ReentrantLock reentrantLock = new ReentrantLock();
Condition condition = reentrantLock.newCondition();
String waitThread = "waitThread";
new Thread(() -> {
reentrantLock.lock();
try {
System.out.println(Thread.currentThread().getName() + " 开始等待 ...");
condition.await();
System.out.println(Thread.currentThread().getName() + " 被唤醒, 运行结束 ...");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}, waitThread).start();
// 阻塞30 毫秒, 主线程先获得锁
Thread.sleep(30);
reentrantLock.lock();
System.out.println("三秒以后开始唤醒 " + waitThread + " 线程");
try {
Thread.sleep(3000);
condition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
reentrantLock.unlock();
}
}
}
运行结果
Condition的注意点
- 实际上,如果说Lock用来代替synchronized,那么Condition就是用来代替相对应的Object.wait/notify的,所以在用法和性质上,几乎都一样
- await方法会自动释放持有的Lock锁,和Object.wait一样,不需要自己手动先释放锁
- 调用await的时候,必须持有锁,否则会抛出异常,和Object.wait一样