【线程基础】Condition类的介绍与使用

邓敏 2021年12月09日 100次浏览

简单介绍一下Condition,Condition是Java1.5开始出现的,其出现的目的就是为了替代传统的Object的wait()、notify()实现线程间的协作。相比传统的方式使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。

常用方法介绍

方法名作用
void await()造成当前线程在接到信号或被中断之前一直处于等待状态。
boolean await(long time, TimeUnit unit)造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态是否超时,超时异常
signal()唤醒一个等待线程。该线程从等待方法返回前必须获得与Condition相关的锁。
signalAll()唤醒所有等待线程。能够从等待方法返回的线程必须获得与Condition相关的锁。
awaitUninterruptibly()造成当前线程在接到信号之前一直处于等待状态。【注意:该方法对中断不敏感】。
awaitUntil(Date deadline)造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。如果没有到指定时间就被通知,则返回true,否则表示到了指定时间,返回返回false。
awaitNanos(long nanosTimeout)造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。返回值表示剩余时间,如果在nanosTimesout之前唤醒,那么返回值 = nanosTimeout - 消耗时间,如果返回值 <= 0 ,则可以认定它已经超时了。

示例代码

public class LockConditionTest {

    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) throws InterruptedException {
        Condition condition = lock.newCondition();

        Thread thread0 = new Thread(()->{
            lock.lock();
            System.out.println(Thread.currentThread().getName()+"锁上了");
            try {
                System.out.println(Thread.currentThread().getName()+"我要开始让出锁了...");
                condition.await();
                System.out.println(Thread.currentThread().getName()+"我又被唤醒了...");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            lock.unlock();
            System.out.println(Thread.currentThread().getName()+"解锁了");
        });

        Thread thread1 = new Thread(()->{
            lock.lock();
            System.out.println(Thread.currentThread().getName()+"锁上了");
            System.out.println("我要开始唤醒condition了");
            condition.signal();
            System.out.println("condition被我唤醒了");
            lock.unlock();
            System.out.println(Thread.currentThread().getName()+"解锁了");
        });

        System.out.println("启动等待线程");
        thread0.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("启动唤醒线程");
        thread1.start();
    }
}

输出结果如下

启动等待线程
Thread-0锁上了
Thread-0我要开始让出锁了...
启动唤醒线程
Thread-1锁上了
我要开始唤醒condition了
condition被我唤醒了
Thread-1解锁了
Thread-0我又被唤醒了...
Thread-0解锁了

从上面的代码和执行结果我们可以看到,其实Condition的await和signal就是线程中wait和notify的作用,并且他们也有一个相同的特性,就是必须加上锁,也就是lock,加锁的好处就是为了能让线程可以按照自己制定的任务顺序的逻辑来执行,这样就保证了线程的安全性。