目录​​(?)​​​​[-]​

  1. ​Guarded Suspension Pattern​
  2. ​Balking Pattern ​
  3. ​Producer-Consumer Pattern ​


 



Guarded Suspension Pattern


     该模式描述的是当一个线程在执行某个操作时,但由于其他资源还没有准备好,需要等待,那么就等待资源准备好才开始自己的操作。我们直接看代码例子:





[java]​view plain​​​​copy​

 


  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 plain​​​​copy​

 


  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 plain​​​​copy​

 


  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>