线程这方面的学习一直不是很充分,今天在看张孝祥的视频的时候看到了一个3个线程轮流工作的例子,有一定的难度,最后运用了condition较方便的实现了。于是又搜索了一下相关资料,汇总如下:
Condition Variables
1. 就像上面反复强调的一样,wait-and-notify机制是与特定对象及其上的锁是绑定在一起的,锁和唤醒对象不能分开,这在某些情况下不是很方便;
2. JDK 1.5提供Condition接口来提供与其它系统几乎一致的condition variables机制;
3. Condition对象由Lock对象的newCondition()方法生成,从而允许一个锁产生多个条件变量,可以根据实际情况来等待不同条件;
4. 该书的例子没有什么特别的实际意义,但JDK 1.5文档中提供了一个例子,能充分说明使用Condition Variables使得程序更加清晰易读,也更有效率:
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class BufferTest{
public static void main(String[] args){
final BoundedBuffer bb = new BoundedBuffer();
new Thread(){
public void run(){
try {
for(int i=0;i<10;i++)
bb.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
try {
for(int i=0;i<10;i++)
bb.put(new Integer(1));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
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 != 0)
notFull.await();
items[putptr] = x;
Thread.sleep(500);
System.out.println("doPut");
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];
Thread.sleep(500);
System.out.println("doTake");
if (++takeptr == items.length)
takeptr = 0;
--count;
notFull.signal();
return x;
} finally {
lock.unlock();
}
}
}
具体的说明请参考JDK 1.5的文档。
5. 除了用lock和await-and-signal来代替synchronized和wait-and-notify外,其语义和机制基本一样。await()在进入前也会自动释放锁,然后再返回前重新获得锁;
6. 使用Condition Variables的原因:
1) 如果使用Lock对象,则必须使用condition variables;
2) 每个Lock对象可以创建多个condition variable.