[Java Concurrent] wait / notifyAll 的简单案例

本案例描述的是,给一辆汽车打蜡、抛光的场景。

Car 是一辆被打蜡抛光的汽车,扮演共享资源的角色。

WaxOnCommand 负责给汽车打蜡,打蜡时需要独占整部车,一次打一部分蜡,等待抛光,然后再打一部分蜡。

BuffCommand 负责给汽车抛光,抛光时需要独占整部车,每一次会将刚打上的蜡抛光,然后等待打蜡,然后再将刚打上的蜡抛光。

WaxOnCommand 、BuffCommand 分别由两个线程相互交替地执行:

  WaxOnCommand 打蜡、等待抛光,BuffCommand 抛光,等待打蜡;

  WaxOnCommand 打蜡、等待抛光,BuffCommand 抛光,等待打蜡;

  WaxOnCommand 打蜡、等待抛光,BuffCommand 抛光,等待打蜡;

  ......

CarWaxBuffDemo 演示这个场景。

代码实现:

Car, 可以改变汽车的打蜡状态,可以等待打蜡状态的改变。输出内容到控制台时,会把当前执行线程一一同输出。

public class Car {

    private boolean isWaxed = false;

    public synchronized void waxed(){
        isWaxed = true;
        print(" car is waxed now ");
        notifyAll();
    }

    public synchronized void unwaxed(){
        isWaxed = false;
        print(" car is unwaxed now ");
        notifyAll();
    }public synchronized void waitingForReWax() throws InterruptedException{
        while (isWaxed == true){
            wait();
        }
        print(" OK to re-wax ");

    }

    public synchronized void waitingForReBuff() throws InterruptedException{
        while (isWaxed == false){
            wait();
        }
        print(" OK to re-Buff ");
    }

    public void print(String msg){
        System.out.println("[" + Thread.currentThread().getName() + " ] " + msg);
    }
}

WaxonComman,给汽车打蜡,主要是两个动作:1.等待可以打蜡,2.打蜡。

import java.util.concurrent.TimeUnit;

public class WaxonCommand implements Runnable {

    private Car car;

    public WaxonCommand(Car car){
        this.car = car;
    }

    @Override
    public void run() {
        try {
            while (true){
                car.waitingForReWax();

                print(" WaxOn take action ");
                TimeUnit.MILLISECONDS.sleep(100);                

                car.waxed();
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

        try {
            TimeUnit.MILLISECONDS.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }                

        print(" Ending WaxOn action ");
    }

    public void print(String msg){
        System.out.println("[" + Thread.currentThread().getName() + " ] " + msg);
    }
}

buffCommand, 给汽车抛光,主要两个动作:1.等待可以抛光,2. 抛光。

import java.util.concurrent.TimeUnit;

public class BuffCommand implements Runnable{

    private Car car;

    public BuffCommand(Car car){
        this.car = car;
    }

    @Override
    public void run() {
        try {
            while (true){
                car.waitingForReBuff();

                print(" Buff take action ");
                TimeUnit.MILLISECONDS.sleep(80);

                car.unwaxed();
            }
        }catch (InterruptedException e) {
            e.printStackTrace();
        }

        try {
            TimeUnit.MILLISECONDS.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }    

        print(" Ending Buff action ");

    }

    public void print(String msg){
        System.out.println("[" + Thread.currentThread().getName() + " ] " + msg);
    }
}

演示给汽车交替打蜡、抛光的场景。给 1 秒的时间,让 WaxonCommand / BuffComand 线程进行打蜡、抛光操作,1 秒后,中断他们的操作。

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

public class CarWaxBuffDemo {

    public static void main() throws InterruptedException{
        ExecutorService exec = Executors.newCachedThreadPool();

        Car car = new Car();
        exec.execute(new BuffCommand(car));
        exec.execute(new WaxonCommand(car));

        TimeUnit.SECONDS.sleep(1);
        System.out.println(" executor stopping ");
        exec.shutdownNow();
    }
}

输出结果:

在被强制中断前,thread-1 和 thread-2 交替进行打蜡、抛光操作。

[pool-1-thread-1 ]  OK to re-wax
[pool-1-thread-1 ]  WaxOn take action
[pool-1-thread-1 ]  car is waxed now
[pool-1-thread-2 ]  OK to re-Buff
[pool-1-thread-2 ]  Buff take action
[pool-1-thread-2 ]  car is unwaxed now
[pool-1-thread-1 ]  OK to re-wax
[pool-1-thread-1 ]  WaxOn take action
[pool-1-thread-1 ]  car is waxed now
[pool-1-thread-2 ]  OK to re-Buff
[pool-1-thread-2 ]  Buff take action
[pool-1-thread-2 ]  car is unwaxed now
[pool-1-thread-1 ]  OK to re-wax
[pool-1-thread-1 ]  WaxOn take action
[pool-1-thread-1 ]  car is waxed now
[pool-1-thread-2 ]  OK to re-Buff
[pool-1-thread-2 ]  Buff take action
[pool-1-thread-2 ]  car is unwaxed now
[pool-1-thread-1 ]  OK to re-wax
[pool-1-thread-1 ]  WaxOn take action
[pool-1-thread-1 ]  car is waxed now
[pool-1-thread-2 ]  OK to re-Buff
[pool-1-thread-2 ]  Buff take action
[pool-1-thread-2 ]  car is unwaxed now
[pool-1-thread-1 ]  OK to re-wax
[pool-1-thread-1 ]  WaxOn take action
[pool-1-thread-1 ]  car is waxed now
[pool-1-thread-2 ]  OK to re-Buff
[pool-1-thread-2 ]  Buff take action
[pool-1-thread-2 ]  car is unwaxed now
[pool-1-thread-1 ]  OK to re-wax
[pool-1-thread-1 ]  WaxOn take action
 executor stopping
java.lang.InterruptedException
    at java.lang.Object.wait(Native Method)
    at java.lang.Object.wait(Object.java:502)
    at concurrencyCooperation.Car.waitingForReBuff(Car.java:29)
    at concurrencyCooperation.BuffCommand.run(BuffCommand.java:17)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
java.lang.InterruptedException: sleep interrupted
    at java.lang.Thread.sleep(Native Method)
    at java.lang.Thread.sleep(Thread.java:340)
    at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
    at concurrencyCooperation.WaxonCommand.run(WaxonCommand.java:20)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
[pool-1-thread-2 ]  Ending Buff action
[pool-1-thread-1 ]  Ending WaxOn action 

参考资料 :

Page 857, wait() and notifyAll(), Thinking in Java

时间: 2024-12-17 01:36:12

[Java Concurrent] wait / notifyAll 的简单案例的相关文章

Java使用MyEclipse构建webService简单案例

 什么是WebServices? 它是一种构建应用程序的普遍模型,可以在任何支持网络通信的操作系统中实施运行;它是一种新的web应用程序分支,是自包含.自描述.模块化的应用,可以发布.定位.通过web调用.Web Service是一个应用组件,它逻辑性的为其他应用程序提供数据与服务.各应用程序通过网络协议和规定的一些标准数据格式(Http,XML,Soap)来访问Web Service,通过Web Service内部执行得到所需结果.Web Service可以执行从简单的请求到复杂商务处理的任何

java concurrent之ReentrantLock

在编码的过程中,有时候我们不得不借助锁同步来保证线程安全.synchronized关键字在上一篇博客中已经介绍:自从JDK5开始,添加了另一种锁机制:ReentrantLock. 二者的区别 1.lock是jdk5之后代码层面实现的,synchronized是JVM层面实现的. 2.synchronized在出现异常的时候能够自动释放锁,而lock必须在finally块中unlock()主动释放锁,否则会死锁. 3.在竞争不激烈的时候synchronized的性能是比lock好一点的,但是当竞争

Java设计模式(一) 简单工厂模式不简单

原创文章,转载请务必将下面这段话置于文章开头处. 本文转发自Jason's Blog,原文链接 http://www.jasongj.com/design_pattern/simple_factory 简单工厂模式使用案例 有一种抽象产品--汽车(Car),同时有多种具体的子类产品,如BenzCar,BMWCar,LandRoverCar.类图如下 作为司机,如果要开其中一种车,比如BenzCar,最直接的做法是直接创建BenzCar的实例,并执行其drive方法,如下 package com.

基于SPARK SQL 读写ORACLE 的简单案例分析常见问题

该文章出自上海harli,偷偷地把女神的东西拿出来,希望女神不要介意. 一.概述 本文主要内容包含Spark SQL读写Oracle表数据的简单案例,并针对案例中比较常见的几个问题给出解决方法. 最后从常见的java.lang.ClassNotFoundException(无法找到驱动类)的异常问题出发,分析相关的几种解决方法,以及各个解决方法之间的异同点. 二.案例中比较常见问题及其解决方法 2.1 启动 首先查看Spark 官网给出的SparkSQL的编程指南部分(http://spark.

Spring Kafka和Spring Boot整合实现消息发送与消费简单案例

本文主要分享下Spring Boot和Spring Kafka如何配置整合,实现发送和接收来自Spring Kafka的消息. 先前我已经分享了Kafka的基本介绍与集群环境搭建方法.关于Kafka的介绍请阅读Apache Kafka简介与安装(一),关于Kafka安装请阅读Apache Kafka安装,关于Kafka集群环境搭建请阅读Apache Kafka集群环境搭建 .这里关于服务器环境搭建不在赘述. Spring Kafka整合Spring Boot创建生产者客户端案例 创建一个kafk

[Design Pattern] Command Pattern 简单案例

Command Pattern, 即命令模式,把一个命令包裹在一个对象里面,将命令对象传递给命令的执行方,属于行为类的设计模式 下面是命令模式的一个简单案例. Stock 代表被操作的对象.Order 定义命令的接口,BuyStock, SellStock 是具体类,实现 Order 接口.Broker 是命令的执行方.CommandPatternDemo 演示命令模式. 代码实现 Order, 命令接口 public interface Order { public void execute(

java concurrent之前戏synchronized

对于多线程共享资源的情况需要进行同步,以避免一个线程的改动被另一个线程的改动所覆盖.最普遍的同步方式就是synchronized.把代码声明为synchronized,有两个重要后果,通常是指该代码具有 原子性(atomicity)和 可见性(visibility). 1.原子性强调的是执行,意味着个时刻,只有一个线程能够执行一段代码,这段代码通过一个monitor object保护.从而防止多个线程在更新共享状态时相互冲突. 2.可见性强调的是结果,它要对付内存缓存和编译器优化的各种反常行为.

Servlet请求头response应用简单案例

Servlet请求头response应用简单案例:访问AServlet重定向到BServlet,5秒后跳到CServlet,并显示图片: AServlet 1 package cn.yzu; 2 import java.io.IOException; 3 import javax.servlet.ServletException; 4 import javax.servlet.http.HttpServlet; 5 import javax.servlet.http.HttpServletReq

[Design Pattern] Filter Pattern 简单案例

Filter Pattern,即过滤模式,通过不同的过滤标准,或者低耦合将过滤标准组合在一起,对一组对象进行过滤,属于结构类的设计模式. 下面是一个过滤模式的简单案例. Criteria 定义过滤接口,CriteriaFemale, CriteriaMale, AndCriteria, OrCriteria 类实现过滤接口.Person 是被过滤的对象.CriteriaPatternDemo 演示过滤模式. 具体代码: 过滤对象 Person 的实现 public class Person {