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

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程序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值