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

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

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

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

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

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

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

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

  ......

CarWaxBuffDemo 演示这个场景。

下面是类之间的关系图。

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

代码实现:

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

  1. public class Car {
  2.  
  3. private boolean isWaxed = false;
  4.  
  5. public synchronized void waxed(){
  6. isWaxed = true;
  7. print(" car is waxed now ");
  8. notifyAll();
  9. }
  10.  
  11. public synchronized void unwaxed(){
  12. isWaxed = false;
  13. print(" car is unwaxed now ");
  14. notifyAll();
  15. }public synchronized void waitingForReWax() throws InterruptedException{
  16. while (isWaxed == true){
  17. wait();
  18. }
  19. print(" OK to re-wax ");
  20.  
  21. }
  22.  
  23. public synchronized void waitingForReBuff() throws InterruptedException{
  24. while (isWaxed == false){
  25. wait();
  26. }
  27. print(" OK to re-Buff ");
  28. }
  29.  
  30. public void print(String msg){
  31. System.out.println("[" + Thread.currentThread().getName() + " ] " + msg);
  32. }
  33. }

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

  1. import java.util.concurrent.TimeUnit;
  2.  
  3. public class WaxonCommand implements Runnable {
  4.  
  5. private Car car;
  6.  
  7. public WaxonCommand(Car car){
  8. this.car = car;
  9. }
  10.  
  11. @Override
  12. public void run() {
  13. try {
  14. while (true){
  15. car.waitingForReWax();
  16.  
  17. print(" WaxOn take action ");
  18. TimeUnit.MILLISECONDS.sleep();
  19.  
  20. car.waxed();
  21. }
  22. }catch (Exception e) {
  23. e.printStackTrace();
  24. }
  25.  
  26. try {
  27. TimeUnit.MILLISECONDS.sleep();
  28. } catch (InterruptedException e) {
  29. e.printStackTrace();
  30. }
  31.  
  32. print(" Ending WaxOn action ");
  33. }
  34.  
  35. public void print(String msg){
  36. System.out.println("[" + Thread.currentThread().getName() + " ] " + msg);
  37. }
  38. }

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

  1. import java.util.concurrent.TimeUnit;
  2.  
  3. public class BuffCommand implements Runnable{
  4.  
  5. private Car car;
  6.  
  7. public BuffCommand(Car car){
  8. this.car = car;
  9. }
  10.  
  11. @Override
  12. public void run() {
  13. try {
  14. while (true){
  15. car.waitingForReBuff();
  16.  
  17. print(" Buff take action ");
  18. TimeUnit.MILLISECONDS.sleep();
  19.  
  20. car.unwaxed();
  21. }
  22. }catch (InterruptedException e) {
  23. e.printStackTrace();
  24. }
  25.  
  26. try {
  27. TimeUnit.MILLISECONDS.sleep();
  28. } catch (InterruptedException e) {
  29. e.printStackTrace();
  30. }
  31.  
  32. print(" Ending Buff action ");
  33.  
  34. }
  35.  
  36. public void print(String msg){
  37. System.out.println("[" + Thread.currentThread().getName() + " ] " + msg);
  38. }
  39. }

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

  1. import java.util.concurrent.ExecutorService;
  2. import java.util.concurrent.Executors;
  3. import java.util.concurrent.TimeUnit;
  4.  
  5. public class CarWaxBuffDemo {
  6.  
  7. public static void main() throws InterruptedException{
  8. ExecutorService exec = Executors.newCachedThreadPool();
  9.  
  10. Car car = new Car();
  11. exec.execute(new BuffCommand(car));
  12. exec.execute(new WaxonCommand(car));
  13.  
  14. TimeUnit.SECONDS.sleep(1);
  15. System.out.println(" executor stopping ");
  16. exec.shutdownNow();
  17. }
  18. }

输出结果:

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

  1. [pool-1-thread-1 ] OK to re-wax
  2. [pool-1-thread-1 ] WaxOn take action
  3. [pool-1-thread-1 ] car is waxed now
  4. [pool-1-thread-2 ] OK to re-Buff
  5. [pool-1-thread-2 ] Buff take action
  6. [pool-1-thread-2 ] car is unwaxed now
  7. [pool-1-thread-1 ] OK to re-wax
  8. [pool-1-thread-1 ] WaxOn take action
  9. [pool-1-thread-1 ] car is waxed now
  10. [pool-1-thread-2 ] OK to re-Buff
  11. [pool-1-thread-2 ] Buff take action
  12. [pool-1-thread-2 ] car is unwaxed now
  13. [pool-1-thread-1 ] OK to re-wax
  14. [pool-1-thread-1 ] WaxOn take action
  15. [pool-1-thread-1 ] car is waxed now
  16. [pool-1-thread-2 ] OK to re-Buff
  17. [pool-1-thread-2 ] Buff take action
  18. [pool-1-thread-2 ] car is unwaxed now
  19. [pool-1-thread-1 ] OK to re-wax
  20. [pool-1-thread-1 ] WaxOn take action
  21. [pool-1-thread-1 ] car is waxed now
  22. [pool-1-thread-2 ] OK to re-Buff
  23. [pool-1-thread-2 ] Buff take action
  24. [pool-1-thread-2 ] car is unwaxed now
  25. [pool-1-thread-1 ] OK to re-wax
  26. [pool-1-thread-1 ] WaxOn take action
  27. [pool-1-thread-1 ] car is waxed now
  28. [pool-1-thread-2 ] OK to re-Buff
  29. [pool-1-thread-2 ] Buff take action
  30. [pool-1-thread-2 ] car is unwaxed now
  31. [pool-1-thread-1 ] OK to re-wax
  32. [pool-1-thread-1 ] WaxOn take action
  33. executor stopping
  34. java.lang.InterruptedException
  35. at java.lang.Object.wait(Native Method)
  36. at java.lang.Object.wait(Object.java:502)
  37. at concurrencyCooperation.Car.waitingForReBuff(Car.java:29)
  38. at concurrencyCooperation.BuffCommand.run(BuffCommand.java:17)
  39. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  40. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  41. at java.lang.Thread.run(Thread.java:745)
  42. java.lang.InterruptedException: sleep interrupted
  43. at java.lang.Thread.sleep(Native Method)
  44. at java.lang.Thread.sleep(Thread.java:340)
  45. at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
  46. at concurrencyCooperation.WaxonCommand.run(WaxonCommand.java:20)
  47. at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  48. at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  49. at java.lang.Thread.run(Thread.java:745)
  50. [pool-1-thread-2 ] Ending Buff action
  51. [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. C/C++ Linux 程序员必须了解的 10 个工具

    1. 基本命令http://mally.stanford.edu/~sr/computing/basic-unix.htmlhttp://pangea.stanford.edu/computing/u ...

  2. Android实现网络多线程断点续传下载(转)

    本示例介绍在Android平台下通过HTTP协议实现断点续传下载. 我们编写的是Andorid的HTTP协议多线程断点下载应用程序.直接使用单线程下载HTTP文件对我们来说是一件非常简单的事.那么,多 ...

  3. .net验证控件

    一.客户端验证(用户体验,减少服务器端压力) 二.服务器端验证(防止恶意攻击,客户端js很容易被绕过) 验证控件:RequiredFieldValidator:字段必填:RangeValidator: ...

  4. aspx页面中获取当前浏览器url

    /假设当前浏览器地址为:http://www.360.net.cn/Group/Index.aspx?id=123 这其中如下介绍: ①."http://"是协议名 ②." ...

  5. 解决第三方DLL没有强签名

    -----转载:http://blog.csdn.net/zyming0815/article/details/5939090 创建一个新的随机密钥对:sn -k myTest.snk 第一步: 将D ...

  6. android6.0源码分析之Camera API2.0下的Capture流程分析

    前面对Camera2的初始化以及预览的相关流程进行了详细分析,本文将会对Camera2的capture(拍照)流程进行分析. 前面分析preview的时候,当预览成功后,会使能ShutterButto ...

  7. TSQL Challenge 2

    和之前发布的TSQL Challenge 1是同一系列的文章,看到那篇学习哪篇,没有固定的顺序,只为锻炼下思维. Compare rows in the same table and group th ...

  8. 学习日记_SSH框架web.xml配置文件篇

    1.参考一:http://www.blogjava.net/yxhxj2006/archive/2012/07/09/382632.html 2.参考二: <!-- web 容器启动spring ...

  9. scrolView

    禁止UIScrollView垂直方向滚动,只允许水平方向滚动 scrollview.contentSize =  CGSizeMake(长度, 0); 禁止UIScrollView水平方向滚动,只允许 ...

  10. Delphi 封装Frame到Dll文件

    做项目的时候,发现这个Frame很好用,为了省空间.调用和修改方便,就将Frame封装到dll(动态链接库)里面,确实很好使. 效果图如下: 上图是临时测试用的,忘了将Frame的align设置成al ...