之前学习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 的阻塞队列的添加和取出,可是这样要这样写呢?
后来,仔细想了想,其实这样写是,这个代码的逻辑应该是这样的:
- 获取一条数据,如果当前集合中没有数据,就阻塞当前线程,放进fullCondition的阻塞队列中;
放入一条数据,如果集合已满,就阻塞当前线程,放进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的文章,可以参考这里