zoukankan      html  css  js  c++  java
  • Java多线程设计模式(二)

     
     
     

    Guarded Suspension Pattern

         该模式描述的是当一个线程在执行某个操作时,但由于其他资源还没有准备好,需要等待,那么就等待资源准备好才开始自己的操作。我们直接看代码例子:
    [java] view plaincopy
     
    1. public class Request {  
    2.   
    3.     private Stringname;  
    4.   
    5.     public Request(String name) {  
    6.         this.name = name;  
    7.     }  
    8.   
    9.     public String getName() {  
    10.         returnname;  
    11.     }  
    12.   
    13.     @Override  
    14.     public String toString() {  
    15.         return"[ Request " +name +" ]";  
    16.     }  
    17. }  
    18.   
    19. public class RequestQueue {  
    20.   
    21.     final private LinkedList<request>queue = new LinkedList<request>();  
    22.   
    23.     public synchronizedvoid putRequest(Request request) {  
    24.         this.queue.addLast(request);  
    25.         notifyAll();  
    26.     }  
    27.   
    28.     publicsynchronized Request getRequest() {  
    29.        // 多线程版本的if  
    30.         while (this.queue.size() <= 0) {  
    31.            try {  
    32.                 wait();  
    33.             }catch (InterruptedException e) {  
    34.             }  
    35.         }  
    36.         return queue.removeFirst();  
    37.     }  
    38. }  
    39.   
    40. import java.util.Random;  
    41.   
    42. public class ClientThreadextends Thread {  
    43.   
    44.     private Random      random;  
    45.   
    46.     private RequestQueuerequestQueue;  
    47.   
    48.     public ClientThread(RequestQueue requestQueue, String name,long seed) {  
    49.         super(name);  
    50.         this.requestQueue = requestQueue;  
    51.         this.random =new Random(seed);  
    52.     }  
    53.   
    54.     @Override  
    55.     public void run() {  
    56.         for (int i = 0; i < 10000; i++) {  
    57.             Request request = new Request("No." + i);  
    58.             System.out.println(Thread.currentThread().getName() +" requests " + request);  
    59.             this.requestQueue.putRequest(request);  
    60.             try {  
    61.                 Thread.sleep(this.random.nextInt(1000));  
    62.             } catch (InterruptedException e) {  
    63.                 e.printStackTrace();  
    64.             }  
    65.         }  
    66.     }  
    67. }  
    68.   
    69.   
    70. import java.util.Random;  
    71.   
    72. public class ServerThreadextends Thread {  
    73.   
    74.     private Random      random;  
    75.   
    76.     private RequestQueuequeue;  
    77.   
    78.     public ServerThread(RequestQueue queue, String name,long seed) {  
    79.         super(name);  
    80.         this.queue = queue;  
    81.         random =new Random(seed);  
    82.     }  
    83.   
    84.     @Override  
    85.     public void run() {  
    86.         for (int i = 0; i < 10000; i++) {  
    87.             Request request = queue.getRequest();  
    88.             System.out.println(Thread.currentThread().getName() +" handles " + request);  
    89.             try {  
    90.                 Thread.sleep(random.nextInt(1000));  
    91.             } catch (InterruptedException e) {  
    92.             }  
    93.         }  
    94.     }  
    95. }  
    96.   
    97. public class Main {  
    98.     public static void main(String[] args) {  
    99.         RequestQueue queue = new RequestQueue();  
    100.         ServerThread serverThread = new ServerThread(queue,"ServerThread", 3141592l);  
    101.         ClientThread clientThread = new ClientThread(queue,"ClientThread", 6535897l);  
    102.         serverThread.start();  
    103.         clientThread.start();  
    104.     }  
    105. }  
    106.   
    107.     </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线程直接返回。我们来看代码实现:
    [java] view plaincopy
     
    1. import java.io.File;  
    2. import java.io.FileWriter;  
    3. import java.io.IOException;  
    4.   
    5. public class Data {  
    6.   
    7.     private final Stringfilename;  
    8.   
    9.     private String      content;  
    10.   
    11.     privateboolean     changed;  
    12.   
    13.     public Data(String filename, String content) {  
    14.         this.filename = filename;  
    15.         this.content = content;  
    16.         this.changed =true;  
    17.     }  
    18.   
    19.     public synchronizedvoid change(String content) {  
    20.         this.content = content;  
    21.         this.changed =true;  
    22.     }  
    23.   
    24.     publicsynchronizedvoid save() {  
    25.         while (!this.changed) {  
    26.             return;  
    27.         }  
    28.         doSave();  
    29.         this.changed =false;  
    30.     }  
    31.   
    32.     private void doSave() {  
    33.         System.out.println(Thread.currentThread().getName() +"calls doSave, content = "  
    34.                 + this.content);  
    35.         File file = new File(filename);  
    36.         FileWriter writer = null;  
    37.         try {  
    38.             writer = new FileWriter(file, true);  
    39.             writer.write(this.content);  
    40.         } catch (IOException e) {  
    41.   
    42.         } finally {  
    43.             if (writer !=null) {  
    44.                 try {  
    45.                     writer.close();  
    46.                 } catch (IOException e) {  
    47.                     e.printStackTrace();  
    48.                 }  
    49.             }  
    50.         }  
    51.     }  
    52. }  
    53.   
    54. import java.util.Random;  
    55.   
    56. public class ChangerThreadextends Thread {  
    57.   
    58.     private Data  data;  
    59.   
    60.     private Randomrandom =new Random();  
    61.   
    62.     public ChangerThread(String name, Data data) {  
    63.         super(name);  
    64.         this.data = data;  
    65.     }  
    66.   
    67.     @Override  
    68.     public void run() {  
    69.         int i = 0;  
    70.         while (true) {  
    71.             i++;  
    72.             String content = "No." + i;  
    73.             this.data.change(content);  
    74.             try {  
    75.                 Thread.sleep(random.nextInt(1000));  
    76.             } catch (InterruptedException e) {  
    77.             }  
    78.             this.data.save();  
    79.         }  
    80.     }  
    81. }  
    82.   
    83. import java.util.Random;  
    84.   
    85. public class SaverThreadextends Thread {  
    86.   
    87.     private Data  data;  
    88.   
    89.     private Randomrandom =new Random();  
    90.   
    91.     public SaverThread(String name, Data data) {  
    92.         super(name);  
    93.         this.data = data;  
    94.     }  
    95.   
    96.     @Override  
    97.     public void run() {  
    98.         while (true) {  
    99.             this.data.save();  
    100.             try {  
    101.                 Thread.sleep(this.random.nextInt(1000));  
    102.             } catch (InterruptedException e) {  
    103.             }  
    104.         }  
    105.     }  
    106.   
    107.     public static void main(String[] args) {  
    108.         Data data = new Data("data.txt","(empty)");  
    109.         new SaverThread("SaverThread", data).start();  
    110.         new ChangerThread("ChangerThread", data).start();  
    111.     }  
    112. }  

    Producer-Consumer Pattern

    该模式即经典的生产-消费模式。该模式在生产者和消费者之间加入一个“桥梁参与者”,以这个参与者来缓冲线程的处理速度之差。一般会有多个生产者和多个消费者。
    [java] view plaincopy
     
    1. import java.io.Serializable;  
    2. public class Data implements Serializable {  
    3.   
    4.     /** 
    5.      *  
    6.      */  
    7.     private static final long serialVersionUID = 7212370995222659529L;  
    8.   
    9.     private String            name;  
    10.   
    11.     public Data(String name) {  
    12.         this.name = name;  
    13.     }  
    14.   
    15.     @Override  
    16.     public String toString() {  
    17.         return"[ Data name = " +this.name +" ]";  
    18.     }  
    19. }  
    20.   
    21. import java.util.LinkedList;  
    22. /** 
    23.  * 数据传输channel,默认大小100,可以通过构造函数定制channel的大小。channel为FIFO模型 
    24.  */  
    25. public class Channel {  
    26.   
    27.     private final LinkedList<data>buffer     =new LinkedList<data>();  
    28.   
    29.     private int                   bufferSize = 100;  
    30.   
    31.     public Channel() {  
    32.         super();  
    33.     }  
    34.   
    35.     public Channel(int channelSize) {  
    36.         this.bufferSize = channelSize;  
    37.     }  
    38.   
    39.     /** 
    40.      * put数据到channel中,当channel的buffer大小大于或等于指定大小时,方法将进行等待 
    41.      *  
    42.      * @param data 
    43.      */  
    44.     public synchronizedvoid put(Data data) {  
    45.         while (buffer.size() >=this.bufferSize) {  
    46.             try {  
    47.                 wait();  
    48.             } catch (InterruptedException e) {  
    49.             }  
    50.         }  
    51.   
    52.         this.buffer.addLast(data);  
    53.         System.out.println(Thread.currentThread().getName() +" put data " + data);  
    54.         notifyAll();  
    55.     }  
    56.   
    57.     /** 
    58.      * 从channel中获取数据,当channel中没有数据时,进行等待 
    59.      *  
    60.      * @return 
    61.      */  
    62.     public synchronized Data take() {  
    63.         while (this.buffer.size() == 0) {  
    64.             try {  
    65.                 wait();  
    66.             } catch (InterruptedException e) {  
    67.             }  
    68.         }  
    69.         Data data = this.buffer.removeFirst();  
    70.         System.out.println(Thread.currentThread().getName() +" take date " + data);  
    71.         notifyAll();  
    72.         return data;  
    73.     }  
    74. }  
    75.   
    76. import java.util.Random;  
    77. public class ComsumerThreadextends Thread {  
    78.   
    79.     private Channel channel;  
    80.   
    81.     private Random  random =new Random();  
    82.   
    83.     public ComsumerThread(String name, Channel channel) {  
    84.         super(name);  
    85.         this.channel = channel;  
    86.     }  
    87.   
    88.     @Override  
    89.     public void run() {  
    90.         while (true) {  
    91.   
    92.             this.channel.take();  
    93.   
    94.             try {  
    95.                 Thread.sleep(random.nextInt(1000));  
    96.             } catch (InterruptedException e) {  
    97.             }  
    98.         }  
    99.     }  
    100. }  
    101.   
    102. import java.util.Random;  
    103. public class ProducerThreadextends Thread {  
    104.   
    105.     private Channel    channel;  
    106.   
    107.     private Random     random =new Random();  
    108.   
    109.     private staticintdataNo = 0;  
    110.   
    111.     public ProducerThread(String name, Channel channel) {  
    112.         super(name);  
    113.         this.channel = channel;  
    114.     }  
    115.   
    116.     @Override  
    117.     public void run() {  
    118.         while (true) {  
    119.             Data data = new Data("No." + nextDataNo());  
    120.             this.channel.put(data);  
    121.             try {  
    122.                 Thread.sleep(random.nextInt(1000));  
    123.             } catch (InterruptedException e) {  
    124.             }  
    125.         }  
    126.     }  
    127.   
    128.     public staticsynchronizedint nextDataNo() {  
    129.         return ++dataNo;  
    130.     }  
    131. }  
    132.   
    133. public class MainThread {  
    134.   
    135.     public static void main(String[] args) {  
    136.         int channelSize = 1000;  
    137.   
    138.         Channel channel = new Channel(channelSize);  
    139.   
    140.         ProducerThread producer1 = new ProducerThread("Producer1", channel);  
    141.         ProducerThread producer2 = new ProducerThread("Producer2", channel);  
    142.   
    143.         ComsumerThread comsumer1 = new ComsumerThread("Comsumer1", channel);  
    144.         ComsumerThread comsumer2 = new ComsumerThread("Comsumer2", channel);  
    145.         ComsumerThread comsumer3 = new ComsumerThread("Comsumer3", channel);  
    146.   
    147.         producer1.start();  
    148.         producer2.start();  
    149.   
    150.         comsumer1.start();  
    151.         comsumer2.start();  
    152.         comsumer3.start();  
    153.     }  
    154. }  
    155. </data></data>  
    转载 http://blog.csdn.net/shenzhen_liubin/article/details/9774253
  • 相关阅读:
    GO 文档笔记
    GO 切片实力踩坑
    关于接口设计的一些反思
    Jenkins 发布.net core 程序,服务端无法下载nuget包的解决方法 error NU1102: 找不到版本为 (>= 3.1.6) 的包
    RabbitMQ 基础概念进阶
    RabbitMQ 入门之基础概念
    Object.entries()使用
    shadow的属性值介绍
    行内元素的特别之处
    margin的特别之处
  • 原文地址:https://www.cnblogs.com/chenying99/p/3322036.html
Copyright © 2011-2022 走看看