Condition
synchronized与wait()和nitofy()/notifyAll()方法相结合可以实现等待/通知模型,ReentrantLock同样可以,需要借助Condition,且Condition有更好的灵活性,具体体现在:
1、一个Lock里面可以创建多个Condition实例
,实现多路通知
2、notify()方法进行通知时,被通知的线程时Java虚拟机随机选择的,但是ReentrantLock结合Condition可以实现有选择性地通知
,这是非常重要的
注意一下
,await()和signal()之前,必须要先lock()获得锁
,使用完毕在finally中unlock()释放锁,这和wait()/notify()/notifyAll()使用前必须先获得对象锁是一样的:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class ThreadDomain06 {
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();
public void await() {
try {
lock.lock();
System.out.println("await时间为:" + System.currentTimeMillis());
condition.await();
System.out.println("await等待结束");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void signal() {
try {
lock.lock();
System.out.println("signal时间为:" + System.currentTimeMillis());
condition.signal();
} finally {
lock.unlock();
}
}
}
public class MyThread10 {
public static void main(String[] args) throws InterruptedException {
final ThreadDomain06 th = new ThreadDomain06();
Thread thread = new Thread(new MyThread10.aRunner(th), "aThread");
thread.start();
Thread.sleep(3000);
th.signal();
}
static class aRunner implements Runnable {
private ThreadDomain06 thd;
public aRunner(ThreadDomain06 thd) {
this.thd = thd;
}
@Override
public void run() {
{
thd.await();
}
}
}
}
// await时间为:1533117384915
// signal时间为:1533117387918
// await等待结束
结果符合预期,ReentrantLock的Condition实现了等待/通知模型。其实这个例子还证明了一点,Condition的await()方法是释放锁的
,原因也很简单,要是await()方法不释放锁,那么signal()方法又怎么能调用到Condition的signal()方法呢?
注意要是用一个Condition的话,那么多个线程
被该Condition给await()后,调用Condition的signalAll()方法
唤醒的是所有的线程。如果想单独唤醒部分线程
该怎么办呢?new出多个Condition
就可以了,这样也有助于提升程序运行的效率。使用多个Condition的场景是很常见的,像ArrayBlockingQueue里就有。