JAVA并发编程(五)-Condition接口

Scroll Down

JAVA并发编程(五)-Condition接口

Condition接口介绍

Condition接口可以作为wait/notify的替代品来实现等待通知,它为过早解决唤醒问题提供了支持,并且解决了Object.wait(long)无法区分是超时还是正常返回的问题,Condition接口定义的await方法、signal方法和signalAll方法相当于Object.wait(),notify(),notifyAll()方法.

Lock.newCondition()的返回值就是一个Condition()实例,因此调用任意一个显示锁实例的newCondition方法可以创建一个相应的Condition接口.Object.wait()/notify()要求执行线程持有这些方法所属对象的内部锁,Condition.await()/signal()也要求其执行线程持有创建该Condition实例的显示锁,Condition实例也称为条件变量或者条件队列,每个Condition实例内部维护了一个用于存储等待线程的队列(等待队列).如果con1,con2是不同的两个Condition实例,线程con1.await()会导致线程被暂停并存入con1的等待队列中,而con1.signal()可以使con1中的等待队列的任一个线程被唤醒,con1.signalAll()会是con1的等待线程全部被唤醒,但是不会影响con2;每一个Lock可以有任意数据的Condition对象,Condition是与Lock绑定的,所以就有Lock的公平性特性:如果是公平锁,线程为按照FIFO的顺序从Condition.await中释放,如果是非公平锁,那么后续的锁竞争就不保证FIFO顺序了。

Condition接口API

void await() throws InterruptedException;
void awaitUninterruptibly();
long awaitNanos(long nanosTimeout) throws InterruptedException;
boolean await(long time, TimeUnit unit) throws InterruptedException;
boolean awaitUntil(Date deadline) throws InterruptedException;
void signal();
void signalAll();

Condition接口使用方法

public class ConditionUsage {
    private final Lock lock = new ReentrantLock();
    private final Condition condition = lock.newCondition();
    private volatile boolean flag = true;
    public void methodA() throws InterruptedException {
        lock.lock();
        try{
            System.out.println("等待方法,时间为:"+System.currentTimeMillis());
            if (flag) {
                condition.await();
            }
            doAction();
        }finally {
            lock.unlock();
        }
    }
    public void notifyMethod() throws InterruptedException {
        lock.lock();
        try {
            System.out.println("通知方法,时间为:"+System.currentTimeMillis());
            flag = false;
            TimeUnit.MILLISECONDS.sleep(1000);
            condition.signalAll();
        }finally {
            lock.unlock();
        }
    }
    public void doAction(){
        System.out.println("doAction方法,当前时间为:"+System.currentTimeMillis());
    }

    public static void main(String[] args) throws InterruptedException {
        ConditionUsage conditionUsage = new ConditionUsage();
        new Thread(()->{
            try {
                conditionUsage.methodA();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
        new Thread(()->{
            try {
                conditionUsage.notifyMethod();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }).start();
    }
}

最终结果为:

image-20200326014456118