Java并发之Condition接口

Condition 接口简介

任意一个 Java 对象都拥有一组监视器方法(定义在 java.lang.Object 上),主要包括 wait()、wait(long timeout)、notify() 以及 notifyAll() 方法,这些方法与 synchronized 同步关键字配合,可以实现线程之间的等待,唤醒

jdk 1.5 之后提供了 Lock 接口,Lock 又提供了条件 Condition 接口,使得对线程的等待、唤醒操作更加详细和灵活。Condition 接口与 Lock 配合也可以实现线程之间的等待,唤醒;但是这两者在使用方式以及功能特性上还是有差别的

对比项 Object 监视器方法 Condition
前置条件 获取对象的锁 1.调用Lock.lock()获取 2.调用Lock.newCondition()获取Condition对象
调用方式 直接调用,如object.wait() 直接调用,如condition.await()
等待队列个数 一个 多个
当前线程释放锁并进入等待状态 支持 支持
当前线程释放锁并进入等待状态,在等待状态中不响应终端 不支持 支持
当前线程释放锁并进入超时等待状态 支持 支持
当前线程释放锁并进入等待状态到将来的某个时间 不支持 支持
唤醒等待队列中的一个线程 支持 支持
唤醒等待队列中的全部线程 支持 支持
  • 一个 Lock 对象里可以创建多个 condition 实例,线程可以注册在指定的 condition 中从而选择性的进行线程通知,在调度线程上更加灵活
  • 在使用 notify(),notifuAll() 方法进行唤醒时,被调度的线程是由 cpu 随机选择的。但使用 ReentrantLock 结合 condition 是可以实现 选择性通知,这个功能是非常重要的,而且在 condition 类中默认提供的
  • synchronized 就相当于整个 Lock 对象中只有一个单一的 condition 对象,所有的线程都注册在它一个对象上。线程开始 notifyAll() 时,需要通知所有的 WAITING 线程,没有选择权
  • Conditon 中的 await() 对应 Objectwait()
  • Condition 中的 signal() 对应 Objectnotify()
  • Condition 中的 signalAll() 对应 ObjectnotifyAll()

Condition 的应用

@Slf4j
public class ProducerConsumerTest {
   

    private final Lock lock = new ReentrantLock();

    // 通过Lock获取两个Condition实例
    private final Condition addCondition = lock.newCondition();
    private final Condition removeCondition = lock.newCondition();

    private final LinkedList<Integer> resources = new LinkedList<>();

    private final int maxSize;

    public ProducerConsumerTest(int maxSize) {
   
        this.maxSize = maxSize;
    }

    public class Producer implements Runnable {
   

        private final int proSize;

        private Producer(int proSize) {
   
            this.proSize = proSize;
        }

        @Override
        public void run() {
   
            lock.lock();
            try {
   
                for (int i = 1; i < proSize; i++) {
   
                    log.info("已经生产产品数: " + i + "\t现仓储量总量:" + resources.size());
                    resources.add(i);
                    while (resources.size() >= maxSize) {
   
                        log.info("当前仓库已满,等待消费...");
                        try {
   
                            // 进入阻塞状态
                            addCondition.await();
                        } catch (InterruptedException e) {
   
                            e.printStackTrace();
                        }
                    }
                    // 唤醒消费者
                    removeCondition.signal();
                }
            } finally {
   
                lock.unlock();
            }
        }
    }
    
    public class Consumer implements Runnable {
   

        @Override
        public void run() {
   
            String threadName = Thread.currentThread().getName();
            while (true) {
   
                lock.lock();
                try {
   
                    while (resources.size() <= 0) {
   
                        log.info(threadName + " 当前仓库没有产品,请稍等...");
                        try {
   
                            // 进入阻塞状态
                            removeCondition.await();
                        } catch (InterruptedException e) {
   
                            e.printStackTrace();
                        }
  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值