• Java多线程设计模式(四)


     

    Future Pattern

          在Thread-Per-Message Pattern中,我们研究过“收到每个请求建立一个线程”的做法,但这样的请求是不要求有返回值的。如果当需要返回值,但由于后台处理需要很久,返回值 不能马上获取,那么就可以使用 Future Pattern。Future Pattern同样会每个请求建立一个线程处理,同时会马上返回一个对象,但该对象并不是真正的返回值,真正的返回值可能现在还没有准备好,不过客户端可 以根据这个返回对象,在之后的时间来获取真正的返回值。

    [java] view plaincopy
     
    1. public interface Data {  
    2.     public String getContent();  
    3. }  
    4.   
    5.   
    6. public class RealData implements Data {  
    7.   
    8.     private String content;  
    9.   
    10.     public RealData(int count, char c) {  
    11.         System.out.println("making RealData(" + count + ", " + c + ") Begin.");  
    12.         char[] buffer = new char[count];  
    13.         for (int i = 0; i < count; i++) {  
    14.             buffer[i] = c;  
    15.             slowly();  
    16.         }  
    17.         this.content = String.valueOf(buffer);  
    18.         System.out.println("making RealData(" + count + ", " + c + ") End.");  
    19.     }  
    20.   
    21.     @Override  
    22.     public String getContent() {  
    23.         return this.content;  
    24.     }  
    25.   
    26.     private void slowly() {  
    27.         try {  
    28.             Thread.sleep(100);  
    29.         } catch (InterruptedException e) {  
    30.         }  
    31.     }  
    32. }  
    33.   
    34. public class FutureData implements Data {  
    35.   
    36.     private RealData realData;  
    37.   
    38.     private boolean  ready = false;  
    39.   
    40.     public synchronized void setRealData(RealData realData) {  
    41.         if (ready) {  
    42.             return;  
    43.         }  
    44.         this.realData = realData;  
    45.         this.ready = true;  
    46.         notifyAll();  
    47.     }  
    48.   
    49.     @Override  
    50.     public synchronized String getContent() {  
    51.         while (!ready) {  
    52.             try {  
    53.                 wait();  
    54.             } catch (InterruptedException e) {  
    55.             }  
    56.         }  
    57.         return this.realData.getContent();  
    58.     }  
    59. }  
    60.   
    61.   
    62. public class Host {  
    63.   
    64.     public Data handle(final int count, final char c) {  
    65.   
    66.         System.out.println("handle ( " + count + ", " + c + ") Begin.");  
    67.         final FutureData futureData = new FutureData();  
    68.         new Thread() {  
    69.             @Override  
    70.             public void run() {  
    71.                 RealData realData = new RealData(count, c);  
    72.                 futureData.setRealData(realData);  
    73.             }  
    74.         }.start();  
    75.   
    76.         System.out.println("handle ( " + count + ", " + c + ") End.");  
    77.         return futureData;  
    78.     }  
    79. }  
    80.   
    81.   
    82. public class Main {  
    83.   
    84.     public static void main(String[] args) {  
    85.         System.out.println("main Begin.");  
    86.         Host host = new Host();  
    87.         Data data1 = host.handle(10'a');  
    88.         Data data2 = host.handle(20'b');  
    89.         Data data3 = host.handle(30'c');  
    90.   
    91.         System.out.println("main other job Begin.");  
    92.         try {  
    93.             Thread.sleep(2000);  
    94.         } catch (InterruptedException e) {  
    95.         }  
    96.         System.out.println("main other job End.");  
    97.   
    98.         System.out.println("data1 = " + data1.getContent());  
    99.         System.out.println("data2 = " + data2.getContent());  
    100.         System.out.println("data3 = " + data3.getContent());  
    101.   
    102.         System.out.println("main End.");  
    103.     }  
    104. }  

            在Worker Thread Pattern中,我们讨论过“方法调用”和“方法执行”的分离。而Future Pattern 分离了“准备返回值”和“使用返回值”。我们在Futtern Pattern中,可以看到设计模式Proxy Pattern的实现。

    Two-Phase Termination Pattern

          Two-Phase Termination Pattern很简单,但该模式提供了一种结束线程的优雅方法。java.lang.Thread类有一个用来强制结束掉线程的stop()方法。但是 stop方法已经不建议使用(deprecated),原因是stop()方法会使实例丧失安全性的保障。使用stop()方法时,线程会抛出 java.lang.ThreadDeath异常而马上结束,即使该线程现在正在执行灵界区间(例如synchronized方法的中间),也会马上结 束。
    [java] view plaincopy
     
    1. public class CountupThread extends Thread {  
    2.   
    3.     private boolean isShutdown = false;  
    4.   
    5.     private int     count      = 0;  
    6.   
    7.     @Override  
    8.     public void run() {  
    9.   
    10.         try {  
    11.             while (isShutdown) {  
    12.                 doWork();  
    13.             }  
    14.         } catch (InterruptedException e) {  
    15.   
    16.         } finally {  
    17.             doShutdown();  
    18.         }  
    19.   
    20.     }  
    21.   
    22.     public void shutdownReqeust() {  
    23.         this.isShutdown = true;  
    24.         interrupt();  
    25.     }  
    26.   
    27.     private void doShutdown() {  
    28.         System.out.println("doShutdown: current count is " + this.count);  
    29.     }  
    30.   
    31.     private void doWork() throws InterruptedException {  
    32.         System.out.println("curren count is " + ++count);  
    33.         Thread.sleep(500);  
    34.     }  
    35.   
    36.     public static void main(String[] args) {  
    37.         System.out.println("main Begin.");  
    38.   
    39.         CountupThread countupThread = new CountupThread();  
    40.         countupThread.start();  
    41.   
    42.         try {  
    43.             Thread.sleep(100000);  
    44.         } catch (InterruptedException e) {  
    45.         }  
    46.         System.out.println("main : shutdown request.");  
    47.         countupThread.shutdownReqeust();  
    48.   
    49.         System.out.println("main : join");  
    50.   
    51.         // 等待线程结束  
    52.         try {  
    53.             countupThread.join();  
    54.         } catch (InterruptedException e) {  
    55.         }  
    56.         System.out.println("main End.");  
    57.     }  
    58. }  


    Thread-Specific Storage Pattern

    Thread-Specific Storage Pattern就是“线程独有的存储库”、“针对每个线程提供的内存空间”的意义。java.lang.ThreadLocal的实例可以想象成一种集合 架构(collection)或许会比较好理解。ThreadLocal的实例只有一个,管理多个对象。
    [java] view plaincopy
     
    1. public class Log {  
    2.   
    3.     private static final ThreadLocal<TSLog> tsLogCollection = new ThreadLocal<TSLog>();  
    4.   
    5.     public static void println(String s) {  
    6.         getTSLog().printWrite(s);  
    7.     }  
    8.   
    9.     public static void close() {  
    10.         getTSLog().close();  
    11.     }  
    12.   
    13.     private static TSLog getTSLog() {  
    14.         TSLog tsLog = tsLogCollection.get();  
    15.         // 如果线程时第一次调用,新建立新文件并注册log  
    16.         if (tsLog == null) {  
    17.             tsLog = new TSLog(Thread.currentThread().getName() + "-log.txt");  
    18.             tsLogCollection.set(tsLog);  
    19.         }  
    20.         return tsLog;  
    21.     }  
    22. }  
    23.   
    24.   
    25. import java.io.FileNotFoundException;  
    26. import java.io.PrintWriter;  
    27.   
    28. public class TSLog {  
    29.   
    30.     private PrintWriter writer;  
    31.   
    32.     public TSLog(String filename) {  
    33.         try {  
    34.             this.writer = new PrintWriter(filename);  
    35.         } catch (FileNotFoundException e) {  
    36.         }  
    37.     }  
    38.   
    39.     public void printWrite(String s) {  
    40.         writer.println(s);  
    41.     }  
    42.   
    43.     public void close() {  
    44.         writer.println("===========End of log===========");  
    45.         writer.close();  
    46.     }  
    47. }  
    48.   
    49.   
    50. public class ClientThread extends Thread {  
    51.   
    52.     public ClientThread(String name) {  
    53.         super(name);  
    54.     }  
    55.   
    56.     @Override  
    57.     public void run() {  
    58.         System.out.println(getName() + " Begin.");  
    59.   
    60.         for (int i = 0; i < 10; i++) {  
    61.             Log.println("i = " + i);  
    62.             try {  
    63.                 Thread.sleep(100);  
    64.             } catch (InterruptedException e) {  
    65.             }  
    66.         }  
    67.         Log.close();  
    68.         System.out.println(getName() + " End.");  
    69.     }  
    70.   
    71.     public static void main(String[] args) {  
    72.         new ClientThread("Alice").start();  
    73.         new ClientThread("Bobby").start();  
    74.         new ClientThread("Chris").start();  
    75.     }  
    76. }  


    Active Object Pattern

    Active Object Pattern其实可以看作是多个多线程模式和多个设计模式组合成的一种更高级的模式,里面多个对象各司其职,共同协作。Active Object Pattern里面使用到了Producer-Consumer Pattern、Thread-Per-Message Pattern、Future Pattern和设计模式的Proxy Pattern、Command Pattern等。
    Server端代码:
    [java] view plaincopy
     
    1. public interface ActiveObject {  
    2.   
    3.     public Result makeString(int count, char fillchar);  
    4.   
    5.     public void displayString(String string);  
    6. }  
    7.   
    8.   
    9. public class Proxy implements ActiveObject {  
    10.   
    11.     private SchedulerThread scheduler;  
    12.   
    13.     private Servant         servant;  
    14.   
    15.     public Proxy(SchedulerThread scheduler, Servant servant) {  
    16.         this.scheduler = scheduler;  
    17.         this.servant = servant;  
    18.     }  
    19.   
    20.     @Override  
    21.     public Result makeString(int count, char fillchar) {  
    22.         FutureResult future = new FutureResult();  
    23.         MakeStringRequest request = new MakeStringRequest(servant, future, count, fillchar);  
    24.         this.scheduler.invoke(request);  
    25.         return future;  
    26.     }  
    27.   
    28.     @Override  
    29.     public void displayString(String string) {  
    30.         DisplayStringRequest request = new DisplayStringRequest(servant, string);  
    31.         this.scheduler.invoke(request);  
    32.     }  
    33. }  
    34.   
    35. public class Servant implements ActiveObject {  
    36.   
    37.     @Override  
    38.     public Result makeString(int count, char fillchar) {  
    39.         char[] buffer = new char[count];  
    40.         for (int i = 0; i < count; i++) {  
    41.             buffer[i] = fillchar;  
    42.             try {  
    43.                 Thread.sleep(500);  
    44.             } catch (InterruptedException e) {  
    45.             }  
    46.         }  
    47.   
    48.         RealResult result = new RealResult(String.valueOf(buffer));  
    49.         return result;  
    50.     }  
    51.   
    52.     @Override  
    53.     public void displayString(String string) {  
    54.         System.out.println("displayString( " + string + " )");  
    55.         try {  
    56.             Thread.sleep(10);  
    57.         } catch (InterruptedException e) {  
    58.         }  
    59.     }  
    60. }  
    61.   
    62. public interface Result {  
    63.   
    64.     public String getResultValue();  
    65. }  
    66.   
    67.   
    68. public class FutureResult implements Result {  
    69.   
    70.     private Result  result;  
    71.   
    72.     private boolean isReady = false;  
    73.   
    74.     public synchronized void setResult(Result result) {  
    75.         if (isReady) {  
    76.             return;  
    77.         }  
    78.         this.result = result;  
    79.         this.isReady = true;  
    80.         notifyAll();  
    81.     }  
    82.   
    83.     @Override  
    84.     public synchronized String getResultValue() {  
    85.         while (!isReady) {  
    86.             try {  
    87.                 wait();  
    88.             } catch (InterruptedException e) {  
    89.             }  
    90.         }  
    91.         return result.getResultValue();  
    92.     }  
    93.   
    94. }  
    95.   
    96. public class RealResult implements Result {  
    97.   
    98.     private String resultValue;  
    99.   
    100.     public RealResult(String resultValue) {  
    101.         this.resultValue = resultValue;  
    102.     }  
    103.   
    104.     @Override  
    105.     public String getResultValue() {  
    106.         return this.resultValue;  
    107.     }  
    108. }  
    109.   
    110.   
    111. public abstract class MethodRequest {  
    112.   
    113.     protected final Servant      servant;  
    114.   
    115.     protected final FutureResult future;  
    116.   
    117.     public MethodRequest(Servant servant, FutureResult future) {  
    118.         this.servant = servant;  
    119.         this.future = future;  
    120.     }  
    121.   
    122.     public abstract void execute();  
    123.   
    124. }  
    125.   
    126.   
    127. public class MakeStringRequest extends MethodRequest {  
    128.   
    129.     private int  count;  
    130.   
    131.     private char fillchar;  
    132.   
    133.     public MakeStringRequest(Servant servant, FutureResult future, int count, char fillchar) {  
    134.         super(servant, future);  
    135.         this.count = count;  
    136.         this.fillchar = fillchar;  
    137.     }  
    138.   
    139.     @Override  
    140.     public void execute() {  
    141.         Result result = this.servant.makeString(count, fillchar);  
    142.         future.setResult(result);  
    143.     }  
    144. }  
    145.   
    146.   
    147. public class DisplayStringRequest extends MethodRequest {  
    148.   
    149.     private String string;  
    150.   
    151.     public DisplayStringRequest(Servant servant, String string) {  
    152.         super(servant, null);  
    153.         this.string = string;  
    154.     }  
    155.   
    156.     @Override  
    157.     public void execute() {  
    158.         this.servant.displayString(string);  
    159.     }  
    160. }  
    161.   
    162. public class SchedulerThread extends Thread {  
    163.   
    164.     private ActivationQueue queue = new ActivationQueue();  
    165.   
    166.     public void invoke(MethodRequest request) {  
    167.         this.queue.putRequest(request);  
    168.     }  
    169.   
    170.     @Override  
    171.     public void run() {  
    172.         while (true) {  
    173.             this.queue.takeRequest().execute();  
    174.         }  
    175.     }  
    176. }  
    177.   
    178. package activeobject.server;  
    179.   
    180. import java.util.LinkedList;  
    181.   
    182. public class ActivationQueue {  
    183.   
    184.     private final LinkedList<MethodRequest> requestQueue = new LinkedList<MethodRequest>();  
    185.   
    186.     private final int                       queueSize    = 100;  
    187.   
    188.     public synchronized void putRequest(MethodRequest request) {  
    189.         while (this.requestQueue.size() >= queueSize) {  
    190.             try {  
    191.                 wait();  
    192.             } catch (InterruptedException e) {  
    193.             }  
    194.         }  
    195.         this.requestQueue.addLast(request);  
    196.         notifyAll();  
    197.     }  
    198.   
    199.     public synchronized MethodRequest takeRequest() {  
    200.         while (this.requestQueue.size() == 0) {  
    201.             try {  
    202.                 wait();  
    203.             } catch (InterruptedException e) {  
    204.             }  
    205.         }  
    206.   
    207.         MethodRequest request = this.requestQueue.removeFirst();  
    208.         notifyAll();  
    209.         return request;  
    210.     }  
    211. }  
    212.   
    213. public class ActiveObjectFactory {  
    214.   
    215.     public static ActiveObject createActiveObjcet() {  
    216.         Servant servant = new Servant();  
    217.   
    218.         SchedulerThread scheduler = new SchedulerThread();  
    219.   
    220.         Proxy proxy = new Proxy(scheduler, servant);  
    221.   
    222.         scheduler.start();  
    223.   
    224.         return proxy;  
    225.     }  
    226. }  

    UML如下图:



    客户端代码:

    [java] view plaincopy
     
    1. import activeobject.server.ActiveObject;  
    2.   
    3. public class DisplayClientThread extends Thread {  
    4.   
    5.     private ActiveObject activeObj;  
    6.   
    7.     public DisplayClientThread(String name, ActiveObject activeObj) {  
    8.         super(name);  
    9.         this.activeObj = activeObj;  
    10.     }  
    11.   
    12.     @Override  
    13.     public void run() {  
    14.         int i = 0;  
    15.         while (true) {  
    16.             i++;  
    17.             String string = getName() + " No." + i;  
    18.             activeObj.displayString(string);  
    19.         }  
    20.     }  
    21. }  
    22.   
    23. import activeobject.server.ActiveObject;  
    24. import activeobject.server.Result;  
    25.   
    26. public class MakerClientThread extends Thread {  
    27.   
    28.     private final ActiveObject activeObj;  
    29.   
    30.     private final char         fillchar;  
    31.   
    32.     public MakerClientThread(String name, ActiveObject activeObj) {  
    33.         super(name);  
    34.         this.activeObj = activeObj;  
    35.         this.fillchar = name.charAt(0);  
    36.     }  
    37.   
    38.     @Override  
    39.     public void run() {  
    40.         int i = 0;  
    41.         while (true) {  
    42.             i++;  
    43.             Result result = activeObj.makeString(i, fillchar);  
    44.             try {  
    45.                 Thread.sleep(1000);  
    46.             } catch (InterruptedException e) {  
    47.             }  
    48.   
    49.             String resultValue = result.getResultValue();  
    50.             System.out.println(Thread.currentThread().getName() + ":value = " + resultValue);  
    51.         }  
    52.   
    53.     }  
    54. }  
    55.   
    56. import activeobject.server.ActiveObject;  
    57. import activeobject.server.ActiveObjectFactory;  
    58.   
    59. public class Main {  
    60.   
    61.     public static void main(String[] args) {  
    62.         ActiveObject activeObj = ActiveObjectFactory.createActiveObjcet();  
    63.         new MakerClientThread("Alice", activeObj).start();  
    64.         new MakerClientThread("Bobby", activeObj).start();  
    65.         new DisplayClientThread("Chris", activeObj).start();  
    66.     }  
    67. }  
    转载 http://blog.csdn.net/shenzhen_liubin/article/details/9866117
  • 相关阅读:
    HTTP协议
    从Iterator到async/await
    那些年曾谈起的跨域
    设计模式之观察者模式与发布订阅模式
    移动Web深度剖析
    浅析JavaScript异步
    mySql入门-(二)
    C# WEB项目MVC框架原理及约定
    Dynamics CRM 邮箱设置 “允许使用凭据进行电子邮件处理” 被禁用的解决
    Win10系统恢复IE 11浏览器
  • 原文地址:https://www.cnblogs.com/chenying99/p/3322038.html
Copyright © 2020-2023  润新知