天天看点

线程之间的协作await/signal

之前有一个文章讲到线程之间的协作是用到Object类的wait,notify/notifyAll,点击打开链接

在javase5的java.util.concurrent类库中还有额外的显式工具可以用来重写线程之间的协作这个程序。使用互斥并允许挂起的基本类是Condition,你可以通过在Condition调用await()来挂起一个任务。当外部条件发生变化,意味着某个任务应该继续执行时,你可以通过调用signal()来通知这个任务,从而唤醒一个任务,或者调用signalAll()来唤醒所有在这个Condition上被其自身挂起的任务(与使用notifyAll()相比,signalAll()是更安全的方式)。

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Car {
	
	private Lock lock = new ReentrantLock();
	
	private Condition condition = lock.newCondition();
	
        //表示是否上蜡
	private boolean waxOn = false;
	
	public void waxed(){
		lock.lock();
		try{
			waxOn = true; //ready to buffed
			condition.signalAll();
		}finally{
			lock.unlock();
		}
	}
	
	public void buffed(){
		lock.lock();
		try{
			waxOn = false; //ready for another coat of wax
			condition.signalAll();
		}finally{
			lock.unlock();
		}
	}
	
	public void waitForWaxing() throws InterruptedException{
		lock.lock();
		try{
			while(!waxOn){
				condition.await();
			}
		}finally{
			lock.unlock();
		}
	}
	
	public void waitForBuffing() throws InterruptedException{
		lock.lock();
		try{
			if(waxOn){
				condition.await();
			}
		}finally{
			lock.unlock();
		}
	}

}
           
public class WaxOn implements Runnable{

	private Car car;
	
	public WaxOn(Car car){
		this.car = car;
	}
	
	@Override
	public void run() {
		try {
			while(!Thread.interrupted()){
				System.out.println("Wax on.");
				TimeUnit.MILLISECONDS.sleep(200);
				car.waxed();
				car.waitForBuffing();
			}
		} catch (InterruptedException e) {
			System.err.println("Exiting thread interrupt.");
			e.printStackTrace();
		}
		System.out.println("Ending Wax on task.");
	}

}
           
public class WaxOff implements Runnable{

	private Car car;
	
	public WaxOff(Car car){
		this.car = car;
	}
	
	@Override
	public void run() {
		try {
			while(!Thread.interrupted()){
				car.waitForWaxing();
				System.out.println("Wax off.");
				TimeUnit.MILLISECONDS.sleep(200);
				car.buffed();
			}
		} catch (InterruptedException e) {
			System.err.println("Exiting thread interrupt.");
			e.printStackTrace();
		}
		System.out.println("Ending Wax off task.");
	}

}
           
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class LockTest {
	
	public static void main(String[] args) throws InterruptedException{
		Car car = new Car();
		
		ExecutorService executorService = Executors.newCachedThreadPool();
		executorService.execute(new WaxOn(car));
		executorService.execute(new WaxOff(car));
		
		TimeUnit.SECONDS.sleep(3);
		executorService.shutdownNow();
	}

}
           

      通过Lock产生一个Condition对象,这个对象被用来管理任务间的通信。但是,这个Condition对象不包含任何有关处理状态的信息,因此你需要管理额外的表示处理状态的信息,使用boolean waxOn表示是否上蜡。

      每个对lock()的调用都必须紧跟一个try-finally子句,用来保证在所有情况下都可以释放锁。

注意:Lock和Condition对象只有在更加困难的多线程问题中才是必需的。