Thinking in java 涂蜡抛光WaxOnWaxOff程序学习

来源:互联网 发布:pyqt4 linux 安装 编辑:程序博客网 时间:2024/04/27 22:22

1.       Car类

class Car {    //Car有一个单一的布尔属性waxOn ,表示涂蜡•抛光处理的状态。    //初始是可以打蜡的状态    private boolean waxOn = false;    public synchronized void notifyBuffer() {        waxOn = true; // Ready to buff 可以抛光        notifyAll();    }    public synchronized void notifyWax() {        waxOn = false; // Ready for another coat of wax 可以打蜡        notifyAll();    }    //等待打蜡 挂起抛光线程    public synchronized void haltBuffer()            throws InterruptedException {        //一直循环检查 只要是可以打蜡的状态就挂起抛光的线程        while (waxOn == false)            wait();    }    //等待抛光 挂起打蜡线程    public synchronized void haltWax()            throws InterruptedException {        //一直循环检查 只要是可以抛光的状态就挂起打蜡的线程        while (waxOn == true)            wait();    }}

2.       WaxOn类

//打蜡class WaxOn implements Runnable {    private volatile double d = 0.0;    Logger logger = LoggerFactory.getLogger(WaxOn.class);    private Car car;    public WaxOn(Car c) {        car = c;    }    public void run() {        try {            while (!Thread.interrupted()) {                //模拟打蜡 非阻塞                long start = System.currentTimeMillis();                for (int i = 1; i < 100000000; i++)                    d = d + (Math.PI + Math.E) / d;                long end = System.currentTimeMillis();                logger.info(String.valueOf(end-start));                logger.info("Wax On! ");                //将waxOn = true 之后通知抛光线程                car.notifyBuffer();                //挂起打蜡的线程                car.haltWax();            }        } catch (InterruptedException e) {            logger.info("Exiting Wax on via interrupt");        }        logger.info("Ending Wax On task");    }}

3.       WaxOff类

//抛光class WaxOff implements Runnable {    Logger logger = LoggerFactory.getLogger(WaxOff.class);    private Car car;    private volatile double d = 0.0;    public WaxOff(Car c) {        car = c;    }    public void run() {        try {            //使用了中断的惯用法            while (!Thread.interrupted()) {                //初始是可以打蜡的状态                //只要是可以打蜡状态 就将抛光线程挂起                //初始waxOn=off 挂起抛光线程                car.haltBuffer();                //模拟抛光 非阻塞耗时任务                long start = System.currentTimeMillis();                for (int i = 1; i < 100000000; i++)                    d = d + (Math.PI + Math.E) / d;                long end = System.currentTimeMillis();                logger.info(String.valueOf(end-start));                logger.info("Wax Off! ");                //waxOn时获取 将其变为waxOff 之后notifyAll                car.notifyWax();            }        } catch (InterruptedException e) {            logger.info("Exiting Wax off via interrupt");        }        logger.info("Ending Wax Off task");    }}

4.       WaxOMatic类


public class WaxOMatic {    public static void main(String[] args) throws Exception {        Car car = new Car();        ExecutorService exec = Executors.newCachedThreadPool();        //这两个线程都有可能先启动执行        exec.execute(new WaxOff(car));        exec.execute(new WaxOn(car));        TimeUnit.MILLISECONDS.sleep(1200); // Run for a while...        //此时 对于WaxOn Thread 由于其线程挂起,那么直接catch InterruptedException        //对于WaxOff Thread,其正在执行非阻塞的数学计算 此时interrupt,        //首先循环将结束,然后循环会经由while语句的顶部退出        //使用了耗时任务来模拟        exec.shutdownNow(); // Interrupt all tasks    }}

类图:



其时序图为

注意几点:

1. 其任务类中使用的while(!Thread.interrupted()){try{}catch{}}的惯用法,当程序处于wait()下的阻塞状态以及在while中非阻塞操作中这两种状态都可以响应外部中断。前者直接抛出InterruptedException异常,而后者会首先循环将结束,然后循环会经由while语句的顶部退出。

2. 其wait()及notifyAll()的顺序流弄清

首先启动两个线程,这两个线程的先后启动顺序是不确定的,但要最初就保证WaxOn先执行,所以WaxOff线程启动后先挂起线程。之后就是WaxOn WaxOff这两个线程在run方法中不断循环。之后就是在一个循环中修改状态,通知,挂起线程,交叉执行。

自己要能够看着类图把程序完整写出来。


使用BlockingQueue实现WaxOnWaxOff程序见:使用BlockingQueue实现WaxOnWaxOff程序