多线程基础学习十五:了解condition

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/u010173095/article/details/78973217

之前学习lock相关知识的时候,看到多很多次condition这个接口,当时重心在学习lock接口上,就没有怎么关注这个接口,现在就了解一下这个接口。

condition

了解之前这个接口之前,我回想了多线程通信的问题,其中有一种就是使用object的wait、notify、notifyall方法,而我之前学习lock相关知识的时候,并没有看到通信相关的内容,所以据此猜测condition应该有类似上述方法的功能。

看一下condition接口提供的方法:
这里写图片描述

从方法名字就可以看到,condition确实提供了类似的方法,下面的signal与signalAll应该就是和notify、notifyall方法相同的功能。

我具体找了一下condition的实现,发现实现都是以内部类的形式在AQS中实现的,如此说来,具体的调用应该就是:

伪代码:

Lock lock = new Lock();
Condition condition = lock.getCondition()

简单使用

因为自己想不到什么场景会用到condition,所以就从网上找了一个大神写的使用场景:

public class ConditionTest {
    private LinkedList<String> buffer;    //容器
    private int maxSize ;           //容器最大
    private Lock lock;
    private Condition fullCondition;
    private Condition notFullCondition;

    ConditionTest(int maxSize){
        this.maxSize = maxSize;
        buffer = new LinkedList<String>();
        lock = new ReentrantLock();
        fullCondition = lock.newCondition();
        notFullCondition = lock.newCondition();
    }

    public void set(String string) throws InterruptedException {
        lock.lock();    //获取锁
        try {
            while (maxSize == buffer.size()){
                notFullCondition.await();       //满了,添加的线程进入等待状态
            }

            buffer.add(string);
            fullCondition.signal();
        } finally {
            lock.unlock();      //记得释放锁
        }
    }

    public String get() throws InterruptedException {
        String string;
        lock.lock();
        try {
            while (buffer.size() == 0){
                fullCondition.await();
            }
            string = buffer.poll();
            notFullCondition.signal();
        } finally {
            lock.unlock();
        }
        return string;
    }
}

在这个使用场景中,我对condition的方法功能都能理解,无法理解的是,为何要定义两个condition。
获取condition的方法:


public Condition newCondition() {
        return sync.newCondition();
    }
// sync
final ConditionObject newCondition() {
            return new ConditionObject();
        }

可以看到,每调用一次就会生成一个新的condition,每个condition都有自己的链表实现的阻塞队列,这个前提下,notFullCondition的wait和signal方法应该不会影响到fullCondition 的阻塞队列的添加和取出,可是这样要这样写呢?

后来,仔细想了想,其实这样写是,这个代码的逻辑应该是这样的:

  1. 获取一条数据,如果当前集合中没有数据,就阻塞当前线程,放进fullCondition的阻塞队列中;
  2. 放入一条数据,如果集合已满,就阻塞当前线程,放进notFullCondition的阻塞队列中,如果没有满,就放入一条,并让fullCondition取出一条阻塞线程,进行操作,

    基于以上简单分析,如果代码改成下面这样就容易理解一些:

public class ConditionTest {
    private LinkedList<String> buffer;    //容器
    private int maxSize ;           //容器最大
    private Lock lock;
    private Condition fullCondition;
    private Condition noCondition;

    ConditionTest(int maxSize){
        this.maxSize = maxSize;
        buffer = new LinkedList<String>();
        lock = new ReentrantLock();
        fullCondition = lock.newCondition();
        noCondition = lock.newCondition();
    }

    public void set(String string) throws InterruptedException {
        lock.lock();    //获取锁
        try {
            while (maxSize == buffer.size()){
                fullCondition.await();       //满了,添加的线程进入等待状态
            }

            buffer.add(string);
            noCondition.signal();
        } finally {
            lock.unlock();      //记得释放锁
        }
    }

    public String get() throws InterruptedException {
        String string;
        lock.lock();
        try {
            while (buffer.size() == 0){
                noCondition.await();
            }
            string = buffer.poll();
            fullCondition.signal();
        } finally {
            lock.unlock();
        }
        return string;
    }
}

总结

condition实现了对象中的wait、notify、notifyAll方法的功能,但是使用场景限于经验,还无法想到。

最后,这是一个转载较多的关于condition的文章,可以参考这里

猜你喜欢

转载自blog.csdn.net/u010173095/article/details/78973217