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

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

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

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

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

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

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

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

  ......

CarWaxBuffDemo 演示这个场景。

下面是类之间的关系图。

由于 ExecutorServices 的使用和 Command Pattern 很相似,所以参照其 UML 绘制而成。

代码实现:

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(); car.waxed();
}
}catch (Exception e) {
e.printStackTrace();
} try {
TimeUnit.MILLISECONDS.sleep();
} 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(); car.unwaxed();
}
}catch (InterruptedException e) {
e.printStackTrace();
} try {
TimeUnit.MILLISECONDS.sleep();
} 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

[Java Concurrent] 多线程合作 wait / notifyAll 的简单案例的更多相关文章

  1. [Java Concurrent] 多线程合作 producer-consumers / queue 的简单案例

    在多线程环境下,通过 BlockingQueue,实现生产者-消费者场景. Toast 被生产和消费的对象. ToastQueue 继承了 LinkedblockingQueue ,用于中间存储 To ...

  2. java基础之Socket编程概述以及简单案例

    概述: 用来实现网络互连的 不同的计算机上 运行的程序间 可以进行数据交互  也就是用来在不同的电脑间, 进行数据传输. 三大要素: IP地址: 设备(电脑,手机,ipad)在网络中的唯一标识. 组成 ...

  3. Java Tread多线程(0)一个简单的多线程实例

    作者 : 卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/39341887 本文演示,一个简单的多线程实例,并简单分析一下线程. 编程多 ...

  4. Java Tread多线程(1)实现Runnable接口

    作者 : 卿笃军 原文地址:http://blog.csdn.net/qingdujun/article/details/39347245 本文演示,Tread多线程实现Runnable接口,以及简单 ...

  5. Java:多线程,java.util.concurrent.atomic包之AtomicInteger/AtomicLong用法

    1. 背景 java.util.concurrent.atomic这个包是非常实用,解决了我们以前自己写一个同步方法来实现类似于自增长字段的问题. 在Java语言中,增量操作符(++)不是原子的,也就 ...

  6. Java的多线程 简单入门

    Java的多线程 简单入门 首先能够先搞清楚什么是程序.进程.线程,以及它们之间的关系: 定义: 一 程序仅仅是一组指令的有序集合.它是静态的 二 进程是具有一定独立功能的程序关于某个数据集合上的一次 ...

  7. Java的多线程机制系列:(一)总述及基础概念

    前言 这一系列多线程的文章,一方面是个人对Java现有的多线程机制的学习和记录,另一方面是希望能给不熟悉Java多线程机制.或有一定基础但理解还不够深的读者一个比较全面的介绍,旨在使读者对Java的多 ...

  8. java 并发多线程显式锁概念简介 什么是显式锁 多线程下篇(一)

    目前对于同步,仅仅介绍了一个关键字synchronized,可以用于保证线程同步的原子性.可见性.有序性 对于synchronized关键字,对于静态方法默认是以该类的class对象作为锁,对于实例方 ...

  9. Java的多线程实现生产/消费模式

    Java的多线程实现生产/消费模式 在Java的多线程中,我们经常使用某个Java对象的wait(),notify()以及notifyAll() 方法实现多线程的通讯,今天就使用Java的多线程实现生 ...

随机推荐

  1. POJ 2007 Scrambled Polygon 凸包

    Scrambled Polygon Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 7214   Accepted: 3445 ...

  2. Day2 - Python基础2 列表、字典、集合

    Python之路,Day2 - Python基础2   本节内容 列表.元组操作 字符串操作 字典操作 集合操作 文件操作 字符编码与转码 1. 列表.元组操作 列表是我们最以后最常用的数据类型之一, ...

  3. poj 2679 Adventurous Driving(SPFA 负环)

    /* - - 这题做了一天.....粗心害死人啊 题目描述恶心 数据更恶心... 先处理一下能走的边 能走的点(到这建边从终点跑一下.) 然后就是SPFA了 注意负环的判断 */ #include&l ...

  4. ie下面兼容性问题的一些总结

    最后一次搞ie兼容性问题,以后都可以不管了0.0 1.浮动兼容性 1.1IE6下的双边距BUG 在IE6下,块元素有浮动和横向margin的时候,最边上元素的横向margin值会被放大成两倍 解决办法 ...

  5. Excel:您尝试打开的文件的格式与文件扩展名指定的格式不一致

    报错信息: 打开文件时提示"您尝试打开的文件xxx.xls的格式与文件扩展名指定的格式不一致.打开文件前请验证文件没有损坏且来源可信.是否立即打开该文件?",卸载Office 20 ...

  6. Android之声音管理器《AudioManager》的使用以及音量控制

    以下为网上下载然后拼接-- Android声音管理AudioManager使用 手机都有声音模式,声音.静音还有震动,甚至震动加声音兼备,这些都是手机的基本功能.在Android手机中,我们同样可以通 ...

  7. 『重构--改善既有代码的设计』读书笔记----Remove Assignments to Parameters

    C++存在按值传递和按引用传递两种传递方式,Java严格按照按值传递这种方式来进行.以按值传递方式的角度来说,如果你 int test(int a) { ) { a = 1; } return a; ...

  8. (转)Android Studio系列教程一下载与安装 背景Android Studio VS Eclipse准备下载创建HelloWorld项目

    背景 相信大家对Android Studio已经不陌生了,Android Studio是Google于2013 I/O大会针对Android开发推出的新的开发工具,目前很多开源项目都已经在采用,Goo ...

  9. JSON基础知识总结

    JSON基础 一.JSON简介 JSON,全称“JavaScript Object Notation(JavaScript对象表示法)”,起源于JavaScript的对象和数组.JSON,说白了就是J ...

  10. Samba 服务器介绍

    Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件,由服务器及客户端程序构成.SMB(Server Messages Block,信息服务块)是一种在局域网上共享文件和打印机的一种通 ...