天天看点

java多线程协作(使用Condition)

除了Object对象提供了wait(),notify()以及notifyAll()这些方法对java对象进行监视之外,Condition接口也提供了与Object相似的监视器方法,在获取到Lock对象之后,配合Condition 提供的方法,也能进行线程间的协作。使用Condition必须先获取锁,比如可以这样获取一个可重入锁 :Lock lock = new ReentrantLock();  再由Lock对象的 newCondition()方法得到一个Condition对象:Condition condition = lock.newCondition();Condition提供的 await()方法可以让线程进入等待状态,其他线程可以调用signal()或signalAll()将等待的线程唤醒。

以下是用Condition监视器代替Object的监视器的例子

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class TestSignalAll {
	public static void main(String[] args) throws InterruptedException {
		Product product = new Product();
		ExecutorService executor = Executors.newCachedThreadPool();
		executor.execute(new Processer(product));
		executor.execute(new Producer(product));
	}
}

class Product{
	private Lock lock  = new ReentrantLock();//创建一个重入所
	private Condition condition = lock.newCondition();
	
	private boolean produce = false;//默认生产的机器是为完成生产动作的
	public void produce(){
		lock.lock();
		try{
			produce = true;//开始生产
			condition.signalAll();	
		}finally{//保证在任何情况下都会释放锁,以下都有这个动作
			lock.unlock();
		}
		
	}
	public void process(){
		lock.lock();
		try{
			produce = false;
			condition.signalAll();
		}finally{
			lock.unlock();
		}
	}
	
	public void waitForProduce() throws InterruptedException{
		lock.lock();
		try{
			while(produce==false){
				condition.await();
			}
		}finally{
			lock.unlock();
		}
	}
	public void waitForProcess() throws InterruptedException{
		lock.lock();
		try{
			while(produce==true){
				condition.await();
			}
		}finally{
			lock.unlock();
		}
	}
}

class Producer implements Runnable{
	private Product product;
	public Producer(Product p){product = p;}

	@Override
	public void run() {
		while(!Thread.interrupted()){
			System.out.println("生产一个未加工产品+++");
			try {
				TimeUnit.SECONDS.sleep(1);//模拟一个加工过程,5秒之后代表有个未加工的产品生成
				product.produce();//通知所有等待的线程准备获取检查条件,获取控制权,此时produce=true;
				product.waitForProcess();//上一步 produce=true ,到这里因为条件满足,所有进入等待,移交出控制权。
			} catch (InterruptedException e) {
				System.out.println("中断退出");
			}
			
		}
		
	}
}

class Processer implements Runnable{
	private Product product;
	public Processer(Product p){product = p;}
	@Override
	public void run() {
		while(!Thread.interrupted()){
			try {
				product.waitForProduce();//如果 produce 为false则一直在等待,以下动作不会执行
				System.out.println("处理一个产品---");//执行到这里,说明没有进入waitForProduce的等待 ,此时produce 为true
				TimeUnit.SECONDS.sleep(1);
				product.process();//设置produce为false,这个条件会让product.waitForProduce()进入等待状态,同时通知所有等待的线程。
			} catch (InterruptedException e) {
				System.out.println("中断退出");
			}
			
		}
	}
}
           

执行结果跟采用Object的notifyAll()是一样的:

生产一个未加工产品+++

处理一个产品---

生产一个未加工产品+++

处理一个产品---

生产一个未加工产品+++

处理一个产品---

生产一个未加工产品+++

处理一个产品---

......

继续阅读