Future Pattern

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

public interface Data {

public String getContent();

}

public class RealData implements Data {

private String content;

public RealData(int count, char c) {

System.out.println("making RealData(" + count + ", " + c + ") Begin.");

char[] buffer = new char[count];

for (int i = 0; i

buffer[i] = c;

slowly();

}

this.content = String.valueOf(buffer);

System.out.println("making RealData(" + count + ", " + c + ") End.");

}

@Override

public String getContent() {

return this.content;

}

private void slowly() {

try {

Thread.sleep(100);

} catch (InterruptedException e) {

}

}

}

public class FutureData implements Data {

private RealData realData;

private boolean  ready = false;

public synchronized void setRealData(RealData realData) {

if (ready) {

return;

}

this.realData = realData;

this.ready = true;

notifyAll();

}

@Override

public synchronized String getContent() {

while (!ready) {

try {

wait();

} catch (InterruptedException e) {

}

}

return this.realData.getContent();

}

}

public class Host {

public Data handle(final int count, final char c) {

System.out.println("handle ( " + count + ", " + c + ") Begin.");

final FutureData futureData = new FutureData();

new Thread() {

@Override

public void run() {

RealData realData = new RealData(count, c);

futureData.setRealData(realData);

}

}.start();

System.out.println("handle ( " + count + ", " + c + ") End.");

return futureData;

}

}

public class Main {

public static void main(String[] args) {

System.out.println("main Begin.");

Host host = new Host();

Data data1 = host.handle(10, 'a');

Data data2 = host.handle(20, 'b');

Data data3 = host.handle(30, 'c');

System.out.println("main other job Begin.");

try {

Thread.sleep(2000);

} catch (InterruptedException e) {

}

System.out.println("main other job End.");

System.out.println("data1 = " + data1.getContent());

System.out.println("data2 = " + data2.getContent());

System.out.println("data3 = " + data3.getContent());

System.out.println("main End.");

}

}

在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方法的中间),也会马上结

束。

public class CountupThread extends Thread {

private boolean isShutdown = false;

private int     count      = 0;

@Override

public void run() {

try {

while (isShutdown) {

doWork();

}

} catch (InterruptedException e) {

} finally {

doShutdown();

}

}

public void shutdownReqeust() {

this.isShutdown = true;

interrupt();

}

private void doShutdown() {

System.out.println("doShutdown: current count is " + this.count);

}

private void doWork() throws InterruptedException {

System.out.println("curren count is " + ++count);

Thread.sleep(500);

}

public static void main(String[] args) {

System.out.println("main Begin.");

CountupThread countupThread = new CountupThread();

countupThread.start();

try {

Thread.sleep(100000);

} catch (InterruptedException e) {

}

System.out.println("main : shutdown request.");

countupThread.shutdownReqeust();

System.out.println("main : join");

// 等待线程结束

try {

countupThread.join();

} catch (InterruptedException e) {

}

System.out.println("main End.");

}

}

Thread-Specific Storage Pattern

Thread-Specific Storage

Pattern就是“线程独有的存储库”、“针对每个线程提供的内存空间”的意义。java.lang.ThreadLocal的实例可以想象成一种集合

架构(collection)或许会比较好理解。ThreadLocal的实例只有一个,管理多个对象。

public class Log {

private static final ThreadLocal tsLogCollection = new ThreadLocal();

public static void println(String s) {

getTSLog().printWrite(s);

}

public static void close() {

getTSLog().close();

}

private static TSLog getTSLog() {

TSLog tsLog = tsLogCollection.get();

// 如果线程时第一次调用,新建立新文件并注册log

if (tsLog == null) {

tsLog = new TSLog(Thread.currentThread().getName() + "-log.txt");

tsLogCollection.set(tsLog);

}

return tsLog;

}

}

import java.io.FileNotFoundException;

import java.io.PrintWriter;

public class TSLog {

private PrintWriter writer;

public TSLog(String filename) {

try {

this.writer = new PrintWriter(filename);

} catch (FileNotFoundException e) {

}

}

public void printWrite(String s) {

writer.println(s);

}

public void close() {

writer.println("===========End of log===========");

writer.close();

}

}

public class ClientThread extends Thread {

public ClientThread(String name) {

super(name);

}

@Override

public void run() {

System.out.println(getName() + " Begin.");

for (int i = 0; i

Log.println("i = " + i);

try {

Thread.sleep(100);

} catch (InterruptedException e) {

}

}

Log.close();

System.out.println(getName() + " End.");

}

public static void main(String[] args) {

new ClientThread("Alice").start();

new ClientThread("Bobby").start();

new ClientThread("Chris").start();

}

}

Active Object Pattern

Active Object

Pattern其实可以看作是多个多线程模式和多个设计模式组合成的一种更高级的模式,里面多个对象各司其职,共同协作。Active Object

Pattern里面使用到了Producer-Consumer Pattern、Thread-Per-Message Pattern、Future

Pattern和设计模式的Proxy Pattern、Command Pattern等。

Server端代码:

public interface ActiveObject {

public Result makeString(int count, char fillchar);

public void displayString(String string);

}

public class Proxy implements ActiveObject {

private SchedulerThread scheduler;

private Servant         servant;

public Proxy(SchedulerThread scheduler, Servant servant) {

this.scheduler = scheduler;

this.servant = servant;

}

@Override

public Result makeString(int count, char fillchar) {

FutureResult future = new FutureResult();

MakeStringRequest request = new MakeStringRequest(servant, future, count, fillchar);

this.scheduler.invoke(request);

return future;

}

@Override

public void displayString(String string) {

DisplayStringRequest request = new DisplayStringRequest(servant, string);

this.scheduler.invoke(request);

}

}

public class Servant implements ActiveObject {

@Override

public Result makeString(int count, char fillchar) {

char[] buffer = new char[count];

for (int i = 0; i

buffer[i] = fillchar;

try {

Thread.sleep(500);

} catch (InterruptedException e) {

}

}

RealResult result = new RealResult(String.valueOf(buffer));

return result;

}

@Override

public void displayString(String string) {

System.out.println("displayString( " + string + " )");

try {

Thread.sleep(10);

} catch (InterruptedException e) {

}

}

}

public interface Result {

public String getResultValue();

}

public class FutureResult implements Result {

private Result  result;

private boolean isReady = false;

public synchronized void setResult(Result result) {

if (isReady) {

return;

}

this.result = result;

this.isReady = true;

notifyAll();

}

@Override

public synchronized String getResultValue() {

while (!isReady) {

try {

wait();

} catch (InterruptedException e) {

}

}

return result.getResultValue();

}

}

public class RealResult implements Result {

private String resultValue;

public RealResult(String resultValue) {

this.resultValue = resultValue;

}

@Override

public String getResultValue() {

return this.resultValue;

}

}

public abstract class MethodRequest {

protected final Servant      servant;

protected final FutureResult future;

public MethodRequest(Servant servant, FutureResult future) {

this.servant = servant;

this.future = future;

}

public abstract void execute();

}

public class MakeStringRequest extends MethodRequest {

private int  count;

private char fillchar;

public MakeStringRequest(Servant servant, FutureResult future, int count, char fillchar) {

super(servant, future);

this.count = count;

this.fillchar = fillchar;

}

@Override

public void execute() {

Result result = this.servant.makeString(count, fillchar);

future.setResult(result);

}

}

public class DisplayStringRequest extends MethodRequest {

private String string;

public DisplayStringRequest(Servant servant, String string) {

super(servant, null);

this.string = string;

}

@Override

public void execute() {

this.servant.displayString(string);

}

}

public class SchedulerThread extends Thread {

private ActivationQueue queue = new ActivationQueue();

public void invoke(MethodRequest request) {

this.queue.putRequest(request);

}

@Override

public void run() {

while (true) {

this.queue.takeRequest().execute();

}

}

}

package activeobject.server;

import java.util.LinkedList;

public class ActivationQueue {

private final LinkedList requestQueue = new LinkedList();

private final int                       queueSize    = 100;

public synchronized void putRequest(MethodRequest request) {

while (this.requestQueue.size() >= queueSize) {

try {

wait();

} catch (InterruptedException e) {

}

}

this.requestQueue.addLast(request);

notifyAll();

}

public synchronized MethodRequest takeRequest() {

while (this.requestQueue.size() == 0) {

try {

wait();

} catch (InterruptedException e) {

}

}

MethodRequest request = this.requestQueue.removeFirst();

notifyAll();

return request;

}

}

public class ActiveObjectFactory {

public static ActiveObject createActiveObjcet() {

Servant servant = new Servant();

SchedulerThread scheduler = new SchedulerThread();

Proxy proxy = new Proxy(scheduler, servant);

scheduler.start();

return proxy;

}

}

UML如下图:

客户端代码:

import activeobject.server.ActiveObject;

public class DisplayClientThread extends Thread {

private ActiveObject activeObj;

public DisplayClientThread(String name, ActiveObject activeObj) {

super(name);

this.activeObj = activeObj;

}

@Override

public void run() {

int i = 0;

while (true) {

i++;

String string = getName() + " No." + i;

activeObj.displayString(string);

}

}

}

import activeobject.server.ActiveObject;

import activeobject.server.Result;

public class MakerClientThread extends Thread {

private final ActiveObject activeObj;

private final char         fillchar;

public MakerClientThread(String name, ActiveObject activeObj) {

super(name);

this.activeObj = activeObj;

this.fillchar = name.charAt(0);

}

@Override

public void run() {

int i = 0;

while (true) {

i++;

Result result = activeObj.makeString(i, fillchar);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

}

String resultValue = result.getResultValue();

System.out.println(Thread.currentThread().getName() + ":value = " + resultValue);

}

}

}

import activeobject.server.ActiveObject;

import activeobject.server.ActiveObjectFactory;

public class Main {

public static void main(String[] args) {

ActiveObject activeObj = ActiveObjectFactory.createActiveObjcet();

new MakerClientThread("Alice", activeObj).start();

new MakerClientThread("Bobby", activeObj).start();

new DisplayClientThread("Chris", activeObj).start();

}

}

java 线程 设计模式_Java多线程设计模式(四)相关推荐

  1. java线程设计模式_JAVA多线程设计模式

    漫谈UML UML 类图 类和层次结构的关系 接口与实现 聚合 访问控制 类间的关联性 顺序图 处理流程和对象间的协调 时序图 Introduction 1 Java语言的线程 Java语言的线程 何 ...

  2. java线程钥匙_Java多线程并发编程/锁的理解

    一.前言 最近项目遇到多线程并发的情景(并发抢单&恢复库存并行),代码在正常情况下运行没有什么问题,在高并发压测下会出现:库存超发/总库存与sku库存对不上等各种问题. 在运用了 限流/加锁等 ...

  3. java线程池_Java多线程并发:线程基本方法+线程池原理+阻塞队列原理技术分享...

    线程基本方法有哪些? 线程相关的基本方法有 wait,notify,notifyAll,sleep,join,yield 等. 线程等待(wait) 调用该方法的线程进入 WAITING 状态,只有等 ...

  4. java线程基础_Java多线程基础

    前言 在我们工作和学习的过程中,Java线程我们或多或少的都会用到,但是在使用的过程上并不是很顺利,会遇到各种各样的坑,这里我通过讲解Thread类中的核心方法,以求重点掌握以下关键技术点: 线程的启 ...

  5. java线程入门_java多线程快速入门(一)

    1.什么是进程 比如:QQ.QQ游戏.eclipse都是进程,可以通过任务管理器查看进程 2.进程和线程区别 线程是进程的一部分,一个进程可以包含多个线程,一个线程只能属于一个进程 进程是所有线程的集 ...

  6. java线程 锁_Java多线程(二) 多线程的锁机制

    当两条线程同时访问一个类的时候,可能会带来一些问题.并发线程重入可能会带来内存泄漏.程序不可控等等.不管是线程间的通讯还是线程共享数据都需要使用Java的锁机制控制并发代码产生的问题.本篇总结主要著名 ...

  7. java 线程 组成_java多线程

    一:基本知识点 1.1线程与进程区别: 1.进程是资源分配的最小单位,线程是CPU调度的最小单位 2.一个进程由一个或多个线程组成 3.进程之间相互独立,每个进程都有独立的代码和数据空间,但同一进程下 ...

  8. java线程 教程_Java多线程系列教程

    Java多线程系列教程 多线程是Java中不可避免的一个重要主体.从本章开始,我们将展开对多线程的学习.接下来的内容是对Java多线程内容的讲解,涉及到的内容包括,Object类中的wait(), n ...

  9. java线程栅栏_Java 多线程基础 - CyclicBarrier

    我的博客 转载请注明原创出处. 序 java.util.concurrent包里有几个能帮助人们管理相互合作的线程集的类,为多线程常见的应用场景预置了抽象好的类库.在遇到这些应用场景时应该直接重用合适 ...

  10. java线程名_java多线程

    首先讲一下进程和线程的区别: 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程. 线程:同一类线程共享代码和数据空间,每个线程有独立的运行栈 ...

最新文章

  1. Linux 内核中的 GCC 特性(zz)
  2. 【题意分析】1024 Palindromic Number (25 分)_38行代码AC
  3. python调用窗口找到文件,使用Python在Mac OS X中查找当前活动窗口
  4. 人工智能技术在银行客服中心的应用风险
  5. redis学习-当下NoSQL应用场景简介
  6. 英伟达推出新款“煤气灶”Titan RTX,售价近2万,并开源PhysX SDK
  7. Linux和windows下多线程的区别
  8. 51nod 博弈论水题
  9. 传智播客-刘意-java深入浅出精华版学习笔记Day06
  10. Servlet九大内置对象
  11. 从混沌熬到风口:移动FM的五年之争
  12. Scrapy入门案例,抓取美剧天堂的前100最新
  13. [原创]K8_C段旁注查询工具5.0 30款国外主流CMS识别+智能识别未知CMS
  14. Linux下更改DNS地址
  15. IOS苹果ipa重签名工具(苹果签名工具,ios签名工具,支持Windows系统和Macos系统)
  16. 公司人才中介平台的设计与实现
  17. 硬件行业知识体系概要 转载
  18. 瑞萨RA系列-开发环境搭建
  19. win10安装rational rose 2007
  20. [AHK]关于获取文档路径的总结

热门文章

  1. 手机兼职做任务发布悬赏赚钱的APP汇总到底有多少?
  2. AI 场景存储优化:云知声超算平台基于 JuiceFS 的存储实践
  3. Oblog的一些整理
  4. 2021年P气瓶充装新版试题及P气瓶充装证考试
  5. 将论文奇数页与偶数页页眉添加不同的下划线
  6. 多维度分析评价体系:高校教学质量大数据应用解决方案
  7. 已知树节点获取树的节点路径(js树节点路径)
  8. 解决电脑屏幕变黄问题
  9. python如何拼读英语单词怎么写_Python简单的拼写检查
  10. 用userAgent判断手机类型