之前有一个文章讲到线程之间的协作是用到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对象只有在更加困难的多线程问题中才是必需的。