Future Pattern

      在Thread-Per-Message Pattern中,我们研究过“收到每个请求建立一个线程”的做法,但这样的请求是不要求有返回值的。如果当需要返回值,但由于后台处理需要很久,返回值 不能马上获取,那么就可以使用 Future Pattern。Future Pattern同样会每个请求建立一个线程处理,同时会马上返回一个对象,但该对象并不是真正的返回值,真正的返回值可能现在还没有准备好,不过客户端可 以根据这个返回对象,在之后的时间来获取真正的返回值。
  1. public interface Data {
  2. public String getContent();
  3. }
  4. public class RealData implements Data {
  5. private String content;
  6. public RealData(int count, char c) {
  7. System.out.println("making RealData(" + count + ", " + c + ") Begin.");
  8. char[] buffer = new char[count];
  9. for (int i = 0; i < count; i++) {
  10. buffer[i] = c;
  11. slowly();
  12. }
  13. this.content = String.valueOf(buffer);
  14. System.out.println("making RealData(" + count + ", " + c + ") End.");
  15. }
  16. @Override
  17. public String getContent() {
  18. return this.content;
  19. }
  20. private void slowly() {
  21. try {
  22. Thread.sleep(100);
  23. } catch (InterruptedException e) {
  24. }
  25. }
  26. }
  27. public class FutureData implements Data {
  28. private RealData realData;
  29. private boolean  ready = false;
  30. public synchronized void setRealData(RealData realData) {
  31. if (ready) {
  32. return;
  33. }
  34. this.realData = realData;
  35. this.ready = true;
  36. notifyAll();
  37. }
  38. @Override
  39. public synchronized String getContent() {
  40. while (!ready) {
  41. try {
  42. wait();
  43. } catch (InterruptedException e) {
  44. }
  45. }
  46. return this.realData.getContent();
  47. }
  48. }
  49. public class Host {
  50. public Data handle(final int count, final char c) {
  51. System.out.println("handle ( " + count + ", " + c + ") Begin.");
  52. final FutureData futureData = new FutureData();
  53. new Thread() {
  54. @Override
  55. public void run() {
  56. RealData realData = new RealData(count, c);
  57. futureData.setRealData(realData);
  58. }
  59. }.start();
  60. System.out.println("handle ( " + count + ", " + c + ") End.");
  61. return futureData;
  62. }
  63. }
  64. public class Main {
  65. public static void main(String[] args) {
  66. System.out.println("main Begin.");
  67. Host host = new Host();
  68. Data data1 = host.handle(10, 'a');
  69. Data data2 = host.handle(20, 'b');
  70. Data data3 = host.handle(30, 'c');
  71. System.out.println("main other job Begin.");
  72. try {
  73. Thread.sleep(2000);
  74. } catch (InterruptedException e) {
  75. }
  76. System.out.println("main other job End.");
  77. System.out.println("data1 = " + data1.getContent());
  78. System.out.println("data2 = " + data2.getContent());
  79. System.out.println("data3 = " + data3.getContent());
  80. System.out.println("main End.");
  81. }
  82. }

在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方法的中间),也会马上结
束。
  1. public class CountupThread extends Thread {
  2. private boolean isShutdown = false;
  3. private int     count      = 0;
  4. @Override
  5. public void run() {
  6. try {
  7. while (isShutdown) {
  8. doWork();
  9. }
  10. } catch (InterruptedException e) {
  11. } finally {
  12. doShutdown();
  13. }
  14. }
  15. public void shutdownReqeust() {
  16. this.isShutdown = true;
  17. interrupt();
  18. }
  19. private void doShutdown() {
  20. System.out.println("doShutdown: current count is " + this.count);
  21. }
  22. private void doWork() throws InterruptedException {
  23. System.out.println("curren count is " + ++count);
  24. Thread.sleep(500);
  25. }
  26. public static void main(String[] args) {
  27. System.out.println("main Begin.");
  28. CountupThread countupThread = new CountupThread();
  29. countupThread.start();
  30. try {
  31. Thread.sleep(100000);
  32. } catch (InterruptedException e) {
  33. }
  34. System.out.println("main : shutdown request.");
  35. countupThread.shutdownReqeust();
  36. System.out.println("main : join");
  37. // 等待线程结束
  38. try {
  39. countupThread.join();
  40. } catch (InterruptedException e) {
  41. }
  42. System.out.println("main End.");
  43. }
  44. }

Thread-Specific Storage Pattern

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

Active Object Pattern

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

UML如下图:

客户端代码:

  1. import activeobject.server.ActiveObject;
  2. public class DisplayClientThread extends Thread {
  3. private ActiveObject activeObj;
  4. public DisplayClientThread(String name, ActiveObject activeObj) {
  5. super(name);
  6. this.activeObj = activeObj;
  7. }
  8. @Override
  9. public void run() {
  10. int i = 0;
  11. while (true) {
  12. i++;
  13. String string = getName() + " No." + i;
  14. activeObj.displayString(string);
  15. }
  16. }
  17. }
  18. import activeobject.server.ActiveObject;
  19. import activeobject.server.Result;
  20. public class MakerClientThread extends Thread {
  21. private final ActiveObject activeObj;
  22. private final char         fillchar;
  23. public MakerClientThread(String name, ActiveObject activeObj) {
  24. super(name);
  25. this.activeObj = activeObj;
  26. this.fillchar = name.charAt(0);
  27. }
  28. @Override
  29. public void run() {
  30. int i = 0;
  31. while (true) {
  32. i++;
  33. Result result = activeObj.makeString(i, fillchar);
  34. try {
  35. Thread.sleep(1000);
  36. } catch (InterruptedException e) {
  37. }
  38. String resultValue = result.getResultValue();
  39. System.out.println(Thread.currentThread().getName() + ":value = " + resultValue);
  40. }
  41. }
  42. }
  43. import activeobject.server.ActiveObject;
  44. import activeobject.server.ActiveObjectFactory;
  45. public class Main {
  46. public static void main(String[] args) {
  47. ActiveObject activeObj = ActiveObjectFactory.createActiveObjcet();
  48. new MakerClientThread("Alice", activeObj).start();
  49. new MakerClientThread("Bobby", activeObj).start();
  50. new DisplayClientThread("Chris", activeObj).start();
  51. }
  52. }
转载 http://blog.csdn.net/shenzhen_liubin/article/details/9866117

最新文章

  1. 4 多表代替密码之Hill 密码 2实现
  2. English -有感过四六级后的托福单词表-附下载
  3. projecteuler Smallest multiple
  4. linux系统的文件和文件类型
  5. redistribute_prefix
  6. oracle2
  7. Java项目中打开本地文件的方法
  8. javascript 备忘录
  9. [html5] 学习笔记-html5音频视频
  10. IntelliJ Idea设置护眼浅绿色背景方法
  11. 利用EF Core的Join进行多表查询
  12. linux办公软件的使用和病毒防范
  13. 语法的二义性和token的超前扫描
  14. 2018-2019-2 网络对抗技术 20165318 Exp2 后门原理与实践
  15. hello2源代码解析
  16. springmvc 自定义view支持json和jsonp格式数据返回
  17. 浅谈log4j-2
  18. Android Studio Run 'app'安装APK到设备的过程
  19. Eclipse打包Egret App (Egret4.1.0)
  20. easyui datagrid行内编辑

热门文章

  1. webDriver对element进行操作
  2. 超简单让ubuntu开启wifi热点(亲测16.04与14.04可用)
  3. 个人关于python装饰器的白痴理解
  4. 11.redis连接
  5. html 中的media属性
  6. Python nonlocal 与 global 关键字解析
  7. PHP 数组中出现中文乱码,json_encode返回结果为null 或false
  8. re模块之research
  9. systemd 配置文件
  10. Uniform &amp; Attribute &amp; Varying