码迷,mamicode.com
首页 > 编程语言 > 详细

Java并发(三)使用显式的Lock和Condition对象

时间:2015-10-12 10:50:01      阅读:321      评论:0      收藏:0      [点我收藏+]

标签:

    在之前的Java并发(一)wait()与notifyAll()一文中的例子中,我们使用了wait()和notifyAll()来模拟了给汽车打蜡和抛光的情景。在JavaSE5中,还提供了java.util.concurrent.locks.Condition对象供我们使用。你可以在Condition上调用await()来挂起一个任务。当外部条件发生变化,意味着某个任务应该继续执行时,你可以通过调用signal()来通知这个任务,或者调用signalAll()来唤醒所有在这个Condition上被其自身挂起的任务(与使用signal()相比,signalAll()是更安全的方式)。

    下面是WaxOnMatic.java的重写版本,它包含了一个Condition,用来在waitForWaxing()或waitForBuffing()内部挂起一个任务:

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;

class Car {
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();
    private boolean waxOn = false;//是否上蜡
    //上蜡
    public void waxed() {
        lock.lock();
        try {
            waxOn = true;
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }
    //抛光
    public void buffed() {
        lock.lock();
        try {
            waxOn = false;
            condition.signalAll();
        } finally {
            lock.unlock();
        }
    }
    //等待上蜡
    public void waitForWaxing() throws InterruptedException {
        lock.lock();
        try {
            while(waxOn == false) {
                condition.await();
            }
        } finally {
            lock.unlock();
        }
    }
    //等待抛光
    public void waitForBuffing() throws InterruptedException {
        lock.lock();
        try {
            while(waxOn == true) {
                condition.await();
            }
        } finally {
            lock.unlock();
        }
        
    }
}


class WaxOnTask implements Runnable {
    private Car car;
    private String name;
    public WaxOnTask(String name, Car car) {
        this.name = name;
        this.car = car;
    }
    @Override
    public void run() {
        try {
            while(!Thread.interrupted()) {
                System.out.println("[" + name + "] is Wax on!");//正在上蜡
                TimeUnit.MILLISECONDS.sleep(300);
                car.waxed();//上蜡完成
                car.waitForBuffing();//等待抛光
            }
        } catch (InterruptedException e) {
            System.out.println("[" + name + "] Exiting WaxOnTask via interrupt.");
        }
    }
}
class BuffTask implements Runnable {
    private Car car;
    private String name;
    public BuffTask(String name, Car car) {
        this.name = name;
        this.car = car;
    }
    @Override
    public void run() {
        try {
            while(!Thread.interrupted()) {
                car.waitForWaxing();//等待上蜡
                System.out.println("[" + name + "] Buffing...");//正在抛光
                TimeUnit.MILLISECONDS.sleep(300);
                car.buffed();//抛光完成
            }
        } catch (InterruptedException e) {
            System.out.println("[" + name + "] Exiting BuffTask via interrupt.");
        }
    }
}

public class WaxOMatic2 {
    public static void main(String[] args) throws Exception {
        Car car = new Car();
        ExecutorService exec = Executors.newCachedThreadPool();
        //上蜡
        exec.execute(new WaxOnTask("Waxx", car));
        //抛光
        exec.execute(new BuffTask("Buff", car));
        //运行一段时间,停止ExecutorService
        TimeUnit.SECONDS.sleep(3);
        exec.shutdownNow();
    }
}

执行结果:

[Waxx] is Wax on!
[Buff] Buffing...
[Waxx] is Wax on!
[Buff] Buffing...
[Waxx] is Wax on!
[Buff] Buffing...
[Waxx] is Wax on!
[Buff] Buffing...
[Waxx] is Wax on!
[Buff] Buffing...
[Buff] Exiting BuffTask via interrupt.
[Waxx] Exiting WaxOnTask via interrupt.

    从代码中可以看到,Car的构造器中,单个的Lock将产生一个Condition对象,这个对象被用来管理任务之间的通信。但是,这个Condition对象不包含任何有关处理状态的信息,因此你需要管理额外的表示处理状态的信息,即boolean waxOn。

    注意:每个lock()的调用都必须紧跟一个try-finally子句,用来保证在所有情况下都可以释放锁。在使用内建版本时,任务在可以调用await(),signal()或signalAll()之前,必须拥有这个锁。

    另外还需要注意的是,这个解决方案比之前一个更加复杂,在本例中这种复杂性并未使你收货更多。Lock和Condition对象只有在更加困难的多线程问题中才是必需的。

Java并发(三)使用显式的Lock和Condition对象

标签:

原文地址:http://my.oschina.net/itblog/blog/515687

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!