条件变量是Java5线程中很重要的一个概念,顾名思义,条件变量就是表示条件的一种变量。但是必须说明,这里的条件是没有实际含义的,仅仅是个标记而已,并且条件的含义往往通过代码来赋予其含义。
这里的条件和普通意义上的条件表达式有着天壤之别。
条件变量都实现了java.util.concurrent.locks.Condition接口,条件变量的实例化是通过一个Lock对象上调用newCondition()方法来获取的,这样,条件就和一个锁对象绑定起来了。因此,Java中的条件变量只能和锁配合使用,来控制并发程序访问竞争资源的安全。
条件变量的出现是为了更精细控制线程等待与唤醒,在Java5之前,线程的等待与唤醒依靠的是Object对象的wait()和notify()/notifyAll()方法,这样的处理不够精细。
而在Java5中,一个锁可以有多个条件,每个条件上可以有多个线程等待,通过调用await()方法,可以让线程在该条件下等待。当调用signalAll()方法,又可以唤醒该条件下的等待的线程。有关Condition接口的API可以具体参考JavaAPI文档。
条件变量比较抽象,原因是他不是自然语言中的条件概念,而是程序控制的一种手段。
package producerConsumer;
import java.util.LinkedList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class TestCondition {
private LinkedList
myList = new LinkedList
();
private int MAX = 3;
private final Lock lock = new ReentrantLock();
private final Condition full = lock.newCondition();
private final Condition empty = lock.newCondition();
public static void main(String[] args) {
new TestCondition().run();
}
public void run(){
ExecutorService pool= Executors.newFixedThreadPool(10);
Thread c1 = new Consumer();
Thread c2 = new Consumer();
Thread c3 = new Consumer();
Thread c4 = new Consumer();
Thread c5 = new Consumer();
Thread p1 = new Producer();
Thread p2 = new Producer();
Thread p3 = new Producer();
Thread p4 = new Producer();
Thread p5 = new Producer();
pool.execute(c1);
pool.execute(p1);
pool.execute(c2);
pool.execute(p2);
pool.execute(c3);
pool.execute(c4);
pool.execute(c5);
pool.execute(p3);
pool.execute(p4);
pool.execute(p5);
pool.shutdown();
}
class Producer extends Thread{
public void run(){
lock.lock();
try {
while(myList.size()==MAX){
System.out.println("Warning: it's full");
full.await();
}
Product p = new Product("Fruit");
if(myList.add(p)){
System.out.println("Producer: ");
}
empty.signal();
} catch (InterruptedException e) {
System.out.println("Producer is interrupted");
}finally{
lock.unlock();
}
}
}
class Consumer extends Thread{
public void run(){
lock.lock();
try {
while(myList.size()==0){
System.out.println("Warning: it's empty!");
empty.await();
}
Product p = myList.removeLast();
System.out.println("Consumer: "+p);
full.signal();
} catch (InterruptedException e) {
System.out.println("Consumer is interrupted");
}finally{
lock.unlock();
}
}
}
}
Warning: it's empty!
Warning: it's empty!
Warning: it's empty!
Producer:
Consumer: Product [name=Fruit]
Producer:
Producer:
Producer:
Consumer: Product [name=Fruit]
Producer:
Consumer: Product [name=Fruit]
Consumer: Product [name=Fruit]
Consumer: Product [name=Fruit]