Condition类

其实这个类我也忘记的差不多了, 但是经常看看的别人来说这个类,但是我是真的已经忘记了, 所以今天也来学习一下

Condition介绍

Condition是在java 1.5中才出现的,它用来替代传统的Object的wait()、notify()实现线程间的协作,相比使用Object的wait()、notify(),使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。因此通常来说比较推荐使用Condition,阻塞队列实际上是使用了Condition来模拟线程间协作。

Condition是个接口,基本方法就是await() 和 signal()方法, signalAll()

Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以使用
  Conditon中的await()对应Object的wait();

Condition中的signal()对应Object的notify();

Condition中的signalAll()对应Object的notifyAll()。

image.png

使用上面的区别(其实也是需要获取到lock的锁才行)

public class TestCondition {
    final Lock lock = new ReentrantLock();
    final Condition condition = lock.newCondition();

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        TestCondition test = new TestCondition();
        Producer producer = test.new Producer();
        Consumer consumer = test.new Consumer();


        consumer.start();
        producer.start();
    }

    class Consumer extends Thread{

        @Override
        public void run() {
            consume();
        }

        private void consume() {

            try {
                lock.lock();
                System.out.println("我在等一个新信号"+this.currentThread().getName());
                condition.await();

            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally{
                System.out.println("拿到一个信号"+this.currentThread().getName());
                lock.unlock();
            }

        }
    }

    class Producer extends Thread{

        @Override
        public void run() {
            produce();
        }

        private void produce() {
            try {
                lock.lock();
                System.out.println("我拿到锁"+this.currentThread().getName());
                condition.signalAll();
                System.out.println("我发出了一个信号:"+this.currentThread().getName());
            } finally{
                lock.unlock();
            }
        }
    }
}

Condition的执行方式,是当在线程Consumer中调用await方法后,线程Consumer将释放锁,并且将自己沉睡,等待唤醒,线程Producer获取到锁后,开始做事,完毕后,调用Condition的signalall方法,唤醒线程Consumer,线程Consumer恢复执行。

以上说明Condition是一个多线程间协调通信的工具类,使得某个,或者某些线程一起等待某个条件(Condition),只有当该条件具备( signal 或者 signalAll方法被带调用)时 ,这些等待线程才会被唤醒,从而重新争夺锁(只有获取到锁才能从await的地方继续执行)。

基于这个的阻塞队列

package com.xiaomi.browser.filter;



import java.util.PriorityQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * ClassName:    BlockQueue
 * Package:    com.xiaomi.browser.filter
 * Description:
 * Datetime:    2021/4/24   下午4:00
 * Author:   liuwei
 */
public class BlockQueue {

    static PriorityQueue<Integer> queue = new PriorityQueue<>(5);
    static Lock lock = new ReentrantLock();
    static Condition produceCon = lock.newCondition();
    static Condition consumeCon = lock.newCondition();

    public static void main(String[] args) {
        Producer producer = new Producer();
        Consumer consumer = new Consumer();
        producer.start();
        consumer.start();


    }

    static class Consumer extends Thread {
        volatile boolean flag = true;

        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    if (queue.isEmpty()) {
                        System.out.println(" 队列为空等待数据");
                        consumeCon.await();
                    }
                    Integer poll = queue.poll();
                    System.out.println("从队列中取走一个元素"+ poll + "队列中剩余的元素大小为" + queue.size() + "个元素");
                    // 唤醒元素
                    TimeUnit.MICROSECONDS.sleep(200);
                    produceCon.signalAll();
                } catch (Exception e) {
                    System.out.println("抛出元素");
                } finally {
                    // 释放元素
                    lock.unlock();
                }

            }
        }
    }

    static class Producer extends Thread {
        volatile boolean flag = true;

        @Override
        public void run() {
            while (true) {
                lock.lock();
                try {
                    if (queue.size() == 5) {
                        System.out.println(" 队列已满");
                        produceCon.await();
                    }
                    queue.add(1);
                    System.out.println("从队列中塞一个元素队列中剩余的元素大小为" + queue.size() + "个元素");
                    // 唤醒元素
                    consumeCon.signalAll();
                } catch (Exception e) {
                    System.out.println("抛出元素");
                } finally {
                    // 释放元素
                    lock.unlock();
                }

            }
        }
    }

}

Condition接口

condition可以通俗的理解为条件队列。当一个线程在调用了await方法以后,直到线程等待的某个条件为真的时候才会被唤醒。这种方式为线程提供了更加简单的等待/通知模式。Condition必须要配合锁一起使用,因为对共享状态变量的访问发生在多线程环境下。一个Condition的实例必须与一个Lock绑定,因此Condition一般都是作为Lock的内部实现。

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

参考博客

https://blog.csdn.net/a1439775520/article/details/98471610

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容