Guarded Suspension Pattern

     该模式描述的是当一个线程在执行某个操作时,但由于其他资源还没有准备好,需要等待,那么就等待资源准备好才开始自己的操作。我们直接看代码例子:
  1. public class Request {
  2. private Stringname;
  3. public Request(String name) {
  4. this.name = name;
  5. }
  6. public String getName() {
  7. returnname;
  8. }
  9. @Override
  10. public String toString() {
  11. return"[ Request " +name +" ]";
  12. }
  13. }
  14. public class RequestQueue {
  15. final private LinkedList<request>queue = new LinkedList<request>();
  16. public synchronizedvoid putRequest(Request request) {
  17. this.queue.addLast(request);
  18. notifyAll();
  19. }
  20. publicsynchronized Request getRequest() {
  21. // 多线程版本的if
  22. while (this.queue.size() <= 0) {
  23. try {
  24. wait();
  25. }catch (InterruptedException e) {
  26. }
  27. }
  28. return queue.removeFirst();
  29. }
  30. }
  31. import java.util.Random;
  32. public class ClientThreadextends Thread {
  33. private Random      random;
  34. private RequestQueuerequestQueue;
  35. public ClientThread(RequestQueue requestQueue, String name,long seed) {
  36. super(name);
  37. this.requestQueue = requestQueue;
  38. this.random =new Random(seed);
  39. }
  40. @Override
  41. public void run() {
  42. for (int i = 0; i < 10000; i++) {
  43. Request request = new Request("No." + i);
  44. System.out.println(Thread.currentThread().getName() +" requests " + request);
  45. this.requestQueue.putRequest(request);
  46. try {
  47. Thread.sleep(this.random.nextInt(1000));
  48. } catch (InterruptedException e) {
  49. e.printStackTrace();
  50. }
  51. }
  52. }
  53. }
  54. import java.util.Random;
  55. public class ServerThreadextends Thread {
  56. private Random      random;
  57. private RequestQueuequeue;
  58. public ServerThread(RequestQueue queue, String name,long seed) {
  59. super(name);
  60. this.queue = queue;
  61. random =new Random(seed);
  62. }
  63. @Override
  64. public void run() {
  65. for (int i = 0; i < 10000; i++) {
  66. Request request = queue.getRequest();
  67. System.out.println(Thread.currentThread().getName() +" handles " + request);
  68. try {
  69. Thread.sleep(random.nextInt(1000));
  70. } catch (InterruptedException e) {
  71. }
  72. }
  73. }
  74. }
  75. public class Main {
  76. public static void main(String[] args) {
  77. RequestQueue queue = new RequestQueue();
  78. ServerThread serverThread = new ServerThread(queue,"ServerThread", 3141592l);
  79. ClientThread clientThread = new ClientThread(queue,"ClientThread", 6535897l);
  80. serverThread.start();
  81. clientThread.start();
  82. }
  83. }
  84. </request></request>

这段代码的关键在 ReqeustQueue类的getReqeust()方法,在该方法中,判断队列是否小于或等于0,如果是,那么就等待队列有数据之后在进行获取 Request对象的操作,注意这里使用的是while,而非if。Single Threaded Execution Pattern 只有一个线程可以进入临界区,其他线程不能进入,进行等待;而Guarded Suspension Pattern中,线程要不要等待,由警戒条件决定。只有RequestQueue类使用到了wait/notifyAll,Guarded Suspension Pattern的实现是封闭在RequestQueue类里的。

Balking Pattern

该模式的重点是,如果一个请求的资源状态还没有准备好,那么就不进行处理,直接返
回,它与Guarded Suspension Pattern的区别在于Guarded Suspension
Pattern在警戒条件不成立时,线程等待,而Balking Pattern线程直接返回。我们来看代码实现:
  1. import java.io.File;
  2. import java.io.FileWriter;
  3. import java.io.IOException;
  4. public class Data {
  5. private final Stringfilename;
  6. private String      content;
  7. privateboolean     changed;
  8. public Data(String filename, String content) {
  9. this.filename = filename;
  10. this.content = content;
  11. this.changed =true;
  12. }
  13. public synchronizedvoid change(String content) {
  14. this.content = content;
  15. this.changed =true;
  16. }
  17. publicsynchronizedvoid save() {
  18. while (!this.changed) {
  19. return;
  20. }
  21. doSave();
  22. this.changed =false;
  23. }
  24. private void doSave() {
  25. System.out.println(Thread.currentThread().getName() +"calls doSave, content = "
  26. + this.content);
  27. File file = new File(filename);
  28. FileWriter writer = null;
  29. try {
  30. writer = new FileWriter(file, true);
  31. writer.write(this.content);
  32. } catch (IOException e) {
  33. } finally {
  34. if (writer !=null) {
  35. try {
  36. writer.close();
  37. } catch (IOException e) {
  38. e.printStackTrace();
  39. }
  40. }
  41. }
  42. }
  43. }
  44. import java.util.Random;
  45. public class ChangerThreadextends Thread {
  46. private Data  data;
  47. private Randomrandom =new Random();
  48. public ChangerThread(String name, Data data) {
  49. super(name);
  50. this.data = data;
  51. }
  52. @Override
  53. public void run() {
  54. int i = 0;
  55. while (true) {
  56. i++;
  57. String content = "No." + i;
  58. this.data.change(content);
  59. try {
  60. Thread.sleep(random.nextInt(1000));
  61. } catch (InterruptedException e) {
  62. }
  63. this.data.save();
  64. }
  65. }
  66. }
  67. import java.util.Random;
  68. public class SaverThreadextends Thread {
  69. private Data  data;
  70. private Randomrandom =new Random();
  71. public SaverThread(String name, Data data) {
  72. super(name);
  73. this.data = data;
  74. }
  75. @Override
  76. public void run() {
  77. while (true) {
  78. this.data.save();
  79. try {
  80. Thread.sleep(this.random.nextInt(1000));
  81. } catch (InterruptedException e) {
  82. }
  83. }
  84. }
  85. public static void main(String[] args) {
  86. Data data = new Data("data.txt","(empty)");
  87. new SaverThread("SaverThread", data).start();
  88. new ChangerThread("ChangerThread", data).start();
  89. }
  90. }

Producer-Consumer Pattern

该模式即经典的生产-消费模式。该模式在生产者和消费者之间加入一个“桥梁参与者”,以这个参与者来缓冲线程的处理速度之差。一般会有多个生产者和多个消费者。
  1. import java.io.Serializable;
  2. public class Data implements Serializable {
  3. /**
  4. *
  5. */
  6. private static final long serialVersionUID = 7212370995222659529L;
  7. private String            name;
  8. public Data(String name) {
  9. this.name = name;
  10. }
  11. @Override
  12. public String toString() {
  13. return"[ Data name = " +this.name +" ]";
  14. }
  15. }
  16. import java.util.LinkedList;
  17. /**
  18. * 数据传输channel,默认大小100,可以通过构造函数定制channel的大小。channel为FIFO模型
  19. */
  20. public class Channel {
  21. private final LinkedList<data>buffer     =new LinkedList<data>();
  22. private int                   bufferSize = 100;
  23. public Channel() {
  24. super();
  25. }
  26. public Channel(int channelSize) {
  27. this.bufferSize = channelSize;
  28. }
  29. /**
  30. * put数据到channel中,当channel的buffer大小大于或等于指定大小时,方法将进行等待
  31. *
  32. * @param data
  33. */
  34. public synchronizedvoid put(Data data) {
  35. while (buffer.size() >=this.bufferSize) {
  36. try {
  37. wait();
  38. } catch (InterruptedException e) {
  39. }
  40. }
  41. this.buffer.addLast(data);
  42. System.out.println(Thread.currentThread().getName() +" put data " + data);
  43. notifyAll();
  44. }
  45. /**
  46. * 从channel中获取数据,当channel中没有数据时,进行等待
  47. *
  48. * @return
  49. */
  50. public synchronized Data take() {
  51. while (this.buffer.size() == 0) {
  52. try {
  53. wait();
  54. } catch (InterruptedException e) {
  55. }
  56. }
  57. Data data = this.buffer.removeFirst();
  58. System.out.println(Thread.currentThread().getName() +" take date " + data);
  59. notifyAll();
  60. return data;
  61. }
  62. }
  63. import java.util.Random;
  64. public class ComsumerThreadextends Thread {
  65. private Channel channel;
  66. private Random  random =new Random();
  67. public ComsumerThread(String name, Channel channel) {
  68. super(name);
  69. this.channel = channel;
  70. }
  71. @Override
  72. public void run() {
  73. while (true) {
  74. this.channel.take();
  75. try {
  76. Thread.sleep(random.nextInt(1000));
  77. } catch (InterruptedException e) {
  78. }
  79. }
  80. }
  81. }
  82. import java.util.Random;
  83. public class ProducerThreadextends Thread {
  84. private Channel    channel;
  85. private Random     random =new Random();
  86. private staticintdataNo = 0;
  87. public ProducerThread(String name, Channel channel) {
  88. super(name);
  89. this.channel = channel;
  90. }
  91. @Override
  92. public void run() {
  93. while (true) {
  94. Data data = new Data("No." + nextDataNo());
  95. this.channel.put(data);
  96. try {
  97. Thread.sleep(random.nextInt(1000));
  98. } catch (InterruptedException e) {
  99. }
  100. }
  101. }
  102. public staticsynchronizedint nextDataNo() {
  103. return ++dataNo;
  104. }
  105. }
  106. public class MainThread {
  107. public static void main(String[] args) {
  108. int channelSize = 1000;
  109. Channel channel = new Channel(channelSize);
  110. ProducerThread producer1 = new ProducerThread("Producer1", channel);
  111. ProducerThread producer2 = new ProducerThread("Producer2", channel);
  112. ComsumerThread comsumer1 = new ComsumerThread("Comsumer1", channel);
  113. ComsumerThread comsumer2 = new ComsumerThread("Comsumer2", channel);
  114. ComsumerThread comsumer3 = new ComsumerThread("Comsumer3", channel);
  115. producer1.start();
  116. producer2.start();
  117. comsumer1.start();
  118. comsumer2.start();
  119. comsumer3.start();
  120. }
  121. }
  122. </data></data>
转载 http://blog.csdn.net/shenzhen_liubin/article/details/9774253

Java多线程设计模式(二)的更多相关文章

  1. [温故]图解java多线程设计模式(一)

    去年看完的<图解java多线程设计模式>,可惜当时没做笔记,导致后来忘了许多东西,打算再温习下这本书,顺便在这里记录一下~  1.顺序执行.并行.并发 顺序执行:多个操作按照顺序依次执行. ...

  2. java多线程设计模式

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt220 java多线程设计模式 java语言已经内置了多线程支持,所有实现Ru ...

  3. Java多线程(二)关于多线程的CPU密集型和IO密集型这件事

    点我跳过黑哥的卑鄙广告行为,进入正文. Java多线程系列更新中~ 正式篇: Java多线程(一) 什么是线程 Java多线程(二)关于多线程的CPU密集型和IO密集型这件事 Java多线程(三)如何 ...

  4. 简述Java多线程(二)

    Java多线程(二) 线程优先级 Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行. 优先级高的不一定先执行,大多数情况是这样的. 优 ...

  5. Java多线程(二) —— 线程安全、线程同步、线程间通信(含面试题集)

    一.线程安全 多个线程在执行同一段代码的时候,每次的执行结果和单线程执行的结果都是一样的,不存在执行结果的二义性,就可以称作是线程安全的. 讲到线程安全问题,其实是指多线程环境下对共享资源的访问可能会 ...

  6. java多线程系列(二)

    对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...

  7. java多线程系列(二)---对象变量并发访问

    对象变量的并发访问 前言:本系列将从零开始讲解java多线程相关的技术,内容参考于<java多线程核心技术>与<java并发编程实战>等相关资料,希望站在巨人的肩膀上,再通过我 ...

  8. Java多线程设计模式(一)

    目录(?)[-] Java多线程基础 Thread类的run方法和start方法 线程的启动 线程的暂时停在 线程的共享互斥 线程的协调 Single Threaded Execution Patte ...

  9. Java多线程设计模式(4)线程池模式

    前序: Thread-Per-Message Pattern,是一种对于每个命令或请求,都分配一个线程,由这个线程执行工作.它将“委托消息的一端”和“执行消息的一端”用两个不同的线程来实现.该线程模式 ...

  10. Java总结篇系列:Java多线程(二)

    本文承接上一篇文章<Java总结篇系列:Java多线程(一)>. 四.Java多线程的阻塞状态与线程控制 上文已经提到Java阻塞的几种具体类型.下面分别看下引起Java线程阻塞的主要方法 ...

随机推荐

  1. 4_python之路之模拟工资管理系统

    python之路之模拟工资管理系统 1.程序说明:Readme.txt 1.程序文件:salary_management.py info.txt 2.程序文件说明:salary_management. ...

  2. Spring实战之切面编程

    如果要重用通用功能的话,最常见的面向对象技术是继承(inheritance)或委托(delegation).但是,如果在整个应用中都使用相同的基类,继承往往会导致一个脆弱的对象体系:而使用委托可能需要 ...

  3. Vue使用echarts

    Vue使用echarts 该示例使用 vue-cli 脚手架搭建 安装echarts依赖 npm install echarts -S 创建图表 全局引入 main.js // 引入echarts i ...

  4. 03-24 Winform图表Chart

    图表主要分为以下几个部分: 1.Annotations--图形注解集合, 2.ChartAreas--图表区域集合, 3.Legends--图例集合, 4.Series--图表序列集合(即图表数据对象 ...

  5. C# Data Parse

    一.DateTime 方法一:Convert.ToDateTime(string) string格式有要求,必须是yyyy-MM-dd hh:mm:ss 方法二:Convert.ToDateTime( ...

  6. C#并口操作

    using System;using System.Runtime.InteropServices;public class PortAccess { [DllImport("inpout3 ...

  7. django -- url 的 默认值

    在urls.py里可以直接向函数传递默认值,看代码: urls.py from django.conf.urls import url from mytest import views urlpatt ...

  8. vue -Missing space before value for key 'path'vue.js解决空格报错

    webpack.base.config.js文件注释掉下面的东西!! module: { rules: [      /*{        test: /\.(js|vue)$/,        lo ...

  9. golang的array/slice

    相同点 由相同类型的元素组合构成 元素有序排列,0为第一个元素下标 基本使用方法相同 区别 array声明时需要指定容量大小,而且无法修改 slice可通过append增加元素,当容量不够时,会自动扩 ...

  10. vs code 配置spring boot开发环境

    一.环境变量 jdk环境变量一键设置 管理員运行 - 一支小白 - 博客园https://www.cnblogs.com/startnow/p/7416533.html 二.安装插件 1.Java E ...