Condition的基本使用如下:
* Condition是个接口,基本的方法就是await()和signal()方法;
* Condition依赖于Lock接口,生成一个Condition的基本代码是lock.newCondition()
* 调用Condition的await()和signal()方法,都必须在lock保护之内,就是说必须在lock.lock()和lock.unlock之间才可以
* 和Object.wait()方法一样,每次调用Condition的await()方法的时候,当前线程就自动释放了对当前锁的拥有权
前面说了Condition的基本含义,今天这篇说下Condition的一个代码例子;
javadoc里面对Condition有一个绝佳的例子,BoundedBuffer类,就是一个线程安全的有界限的缓存;非常巧妙的利用了Condition,根据来通知不同的线程做不同的事情;
下面先看下具体代码:
class BoundedBuffer { final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100]; int putptr, takeptr, count; public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) notFull.await(); items[putptr] = x; if (++putptr == items.length) putptr = 0; ++count; notEmpty.signal(); } finally { lock.unlock(); } } public Object take() throws InterruptedException { lock.lock(); try { while (count == 0) notEmpty.await(); Object x = items[takeptr]; if (++takeptr == items.length) takeptr = 0; --count; notFull.signal(); return x; } finally { lock.unlock(); } } }
代码意思不复杂,一个有界的buffer,里面是个数组,可以往里面放数据和取数据;
由于该buffer被多个线程共享,所以每次放和取操作的时候都用一个lock保护起来;
每次取数据(take)的时候,
a. 如果当前个数是0(用一个count计数), 那么就调用notEmpty.await等待,锁就释放了;
b. 取数据的索引专门有一个,每次向前一步; 如果到头了就从0开始循环使用
c.如果有数据,那就取一个数据,将count减1,同时调用notfull.signal(),
每次放数据(put)的时候
a.如果count和length相等,也就是满了,那就调用notFull.await等待,释放了锁; 等待有一些take()调用完成之后才会进入
b. 放数据也有一个索引putptr, 放入数据; 如果到头了也从0开始循环使用
c. 调用notempty.signal(); 如果有线程在take()的时候await住了,那么就会被通知到,可以继续进行操作
http://www.hetaoblog.com/myblogs/post/java-concurrent-lock-condition.jhtml