java多线程设计模式笔记之Active Object
来源:互联网 发布:mac看视频缺少插件 编辑:程序博客网 时间:2024/06/06 04:31
今天要说的模式是前几个模式的综合体,也是这个系列的最后的一个模式,叫做接受异步消息的主动对象。与之相关的模式有java多线程设计模式之Future Pattern、 java多线程设计模式之消费者生产者模式、 java多线程设计模式之Guarded Suspension等,如果不了解这几个模式,最好先看下这几个模式。
何为主动对象,一般来说是指自己拥有独立的线程的对象,在这里不只是拥有独立线程,还可从外部接受异步消息,并能配合需要返回处理结果。代码是最好的老师,上代码:
首先是主动对象接口,为什么要接口呢,因为这里使用了代理模式:
public interface ActiveObject { Result makeString(int count,char fillChar); void displayString(String string);}我们的主动对象:
public class Servant implements ActiveObject{ @Override public Result makeString(int count, char fillChar) { char[] buffer = new char[count]; for (int i = 0; i < count; i++) { buffer[i] = fillChar; try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } return new RealResult(new String(buffer)); } @Override public void displayString(String string) { System.out.println("display string"+string); try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } }}两个简单的方法,一个生成一个字符串传入RealResult类对象,一个现实一个字符串。RealResult相信看过FuturePattern就知道是什么意思。至于RealResult代码是什么,稍后会说。
主动对象的代理类,持有主动对象的引用,被客户端实际调用的类,也是主动对象和调度线程SchedulerThread的中介者。至于调度线程,也是稍后再谈。
public class Proxy implements ActiveObject { private final SchedulerThread schedulerThread; private final Servant servant; public Proxy(SchedulerThread schedulerThread, Servant servant) { this.schedulerThread = schedulerThread; this.servant = servant; } public Result makeString(int count,char fillchar){ FutureResult futureResult = new FutureResult(); schedulerThread.invoke(new MakeStringRequest(servant,futureResult,count,fillchar)); return futureResult; } public void displayString(String string){ schedulerThread.invoke(new DisplayStringRequest(servant,string)); }}
这里Proxy持有Servant和SchedulerThread的引用,在makeString的时候将一个FutureResult(作用和Future Pattenr中的FutureResult一样)的对象那传入一个MakeStringRequest的对象,然后SchedulerThread的invoke方法接受MakeStringRequest的对象作为参数。
主动对象的工厂类:
public class ActiveObjectFactory { public static ActiveObject createActiveObject(){ Servant servant = new Servant(); ActivationQueue queue = new ActivationQueue(); SchedulerThread schedulerThread = new SchedulerThread(queue); Proxy proxy = new Proxy(schedulerThread,servant); schedulerThread.start(); return proxy; }}
该类直接和客户端打交道,客户端使用主动对象都是从该类获取,并且返回的是ActiveObject接口,实现了解耦。
调度线程:
public class SchedulerThread extends Thread{ private ActivationQueue activationQueue; public SchedulerThread(ActivationQueue activationQueue) { this.activationQueue = activationQueue; } public void invoke(MethodRequest methodRequest){ activationQueue.putRequest(methodRequest); } @Override public void run() { while (true){ MethodRequest methodRequest = activationQueue.takeRequest(); methodRequest.execute(); } }}
如果看过生产着消费者模式就会觉得很简单,持有一个ActiveationQueue对象(看名字就知道是请求队列),然后invoke方法就是将一个MethodeRequest放入队列,而本身开启的线程则是循环从队列中取出请求执行请求的execute方法。
结合上面的Proxy就能看出,Proxy主要就是将MakeStringRequest和DiaplayStringRequest放入ActiveationQueue对象。
请求队列ActiveationQueue:
public class ActivationQueue { private static final int MAX_REQUEST = 100; private MethodRequest[] methodRequests; //下一个要放的位置 private int tail; //下一个要取的位置 private int head; //蛋糕数量 private int count; public ActivationQueue() { this.methodRequests = methodRequests = new MethodRequest[MAX_REQUEST]; tail = 0; head = 0; count = 0; } public synchronized void putRequest(MethodRequest methodRequest){ while (count >= methodRequests.length){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } methodRequests[tail] = methodRequest; tail = (tail+1)%methodRequests.length; count++; notifyAll(); } public synchronized MethodRequest takeRequest() { while (count <= 0){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } MethodRequest methodRequest = methodRequests[head]; head = (head+1)%methodRequests.length; count--; notifyAll(); return methodRequest; }}
一个很普通的阻塞队列,对生产着消费者模式不熟悉的可以看java多线程设计模式之消费者生产者模式,这是一个很重要的模式。
接下来谈下请求积基类MethodRequest,也就是异步消息。在上面的SchedulerThread的invoke方法,是将一个方法调用转化为一个异步消息,让另一个线程去执行,这也是一种很重要的设计思想。
public abstract class MethodRequest { protected final Servant servant; protected final FutureResult futureResult; public MethodRequest(Servant servant, FutureResult futureResult) { this.servant = servant; this.futureResult = futureResult; } public abstract void execute();}
具体的请求:
public class MakeStringRequest extends MethodRequest{ private final int count; private final char fillChar; public MakeStringRequest(Servant servant, FutureResult futureResult, int count, char fillChar) { super(servant, futureResult); this.count = count; this.fillChar = fillChar; } @Override public void execute() { Result result = servant.makeString(count,fillChar); futureResult.setResult(result); }}
public class DisplayStringRequest extends MethodRequest{ private final String string; public DisplayStringRequest(Servant servant, String string) { super(servant, null); this.string = string; } @Override public void execute() { servant.displayString(string); }}
如果了解 java多线程设计模式之Future Pattern,那很容易理解,在Proxy的makeString方法中返回的是一个Result对象,实际为FutureResult,在这里可以看到FutureResult必须等到Servant的makeString方法(耗时操作)返回RealResult之后才可以持有RealResult对象的引用。
再看下Result:
public abstract class Result { public abstract Object getResultValue();}
ublic class FutureResult extends Result{ private Result result; private boolean ready; public synchronized void setResult(Result result){ this.result = result; ready = true; notifyAll(); } public synchronized Object getResultValue(){ while (!ready){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } return result.getResultValue(); }}
public class RealResult extends Result{ private final Object resultValue; public RealResult(Object resultValue) { this.resultValue = resultValue; } public Object getResultValue() { return resultValue; }}
最后是客户端线程:
public class MakerClientThread extends Thread{ private final ActiveObject activeObject; private final char fillchar; public MakerClientThread(String name, ActiveObject activeObject) { super(name); this.activeObject = activeObject; this.fillchar = name.charAt(0); } @Override public void run() { try { for (int i = 0; true; i++) { Result result = activeObject.makeString(i,fillchar); Thread.sleep(10); String value = (String) result.getResultValue(); System.out.println(Thread.currentThread().getName() + " getValue:" + value); } } catch (InterruptedException e) { e.printStackTrace(); } }}
制作字符串线程通过调用主动对象的makeString得到Result(FutureResult),等待一段时间后从Result中取结果。
public class DisplayClientThread extends Thread { private final ActiveObject activeObject; public DisplayClientThread(String name, ActiveObject activeObject) { super(name); this.activeObject = activeObject; } @Override public void run() { try { for (int i = 0; true; i++) { String string =Thread.currentThread().getName()+ " " + i; activeObject.displayString(string); Thread.sleep(200); } } catch (InterruptedException e) { e.printStackTrace(); } }}
循环调用主动对象的displayString方法。
Main:
public class Main1 { public static void main(String args[]){ ActiveObject activeObject = ActiveObjectFactory.createActiveObject(); new MakerClientThread("A",activeObject).start(); new MakerClientThread("B",activeObject).start(); new DisplayClientThread("C",activeObject).start(); }}
运行结果
display stringC 0
A getValue:
B getValue:
A getValue:A
B getValue:B
display stringC 1
A getValue:AA
B getValue:BB
display stringC 2
display stringC 3
A getValue:AAA
display stringC 4
B getValue:BBB
display stringC 5
A getValue:AAAA
display stringC 6:
..........
这个综合的模式中除了运用了多个多线程的模式外,也运用了面向对象解耦的设计思想,客户端线程和主动对象、调度线程和主动对象它们之间并没有直接的耦合。真正处理数据的只有Servant,但因为有耗时操作,所以放在新的线程SchedulerThread中,这也使得运行Servant的是单线程,所以即使发出请求的客户端线程有多个,也保证了Servant的线程安全。
- java多线程设计模式笔记之Active Object
- Java 多线程编程设计模式 Active Object
- Java多线程编程之Active Object模式
- 多线程设计模式-Active Object
- java设计模式之Active Object
- Java多线程编程模式实战指南一:Active Object模式
- Java多线程编程模式实战指南(一):Active Object模式
- Java 多线程编程设计模式之Immutable Object 模式
- 一步步学习java并发编程模式之Active Object模式(三)java实现active object
- 一步步学习java并发编程模式之Active Object模式(一)什么是active object
- java active object 并发模式
- 设计模式- 主动对象(Active Object)
- 设计模式- 主动对象(Active Object)
- 设计模式- 主动对象(Active Object)
- [置顶] Java多线程编程模式实战指南(一):Active Object模式(上)
- [置顶] Java多线程编程模式实战指南(一):Active Object模式(下)
- Java多线程编程模式实战指南一:Active Object模式(上)
- Java多线程编程模式实战指南一:Active Object模式(下)
- 【常用模板】 完全背包
- muduo库的LogFile日志文件类剖析
- 临界段
- Java单例模式
- 机器学习的数学基础
- java多线程设计模式笔记之Active Object
- java数据结构与算法之递归思维(让我们更通俗地理解递归)
- iOS6-10新特性总结
- springboot整合dubbox
- iOS 手机网络类型和运营商怎么获取
- 拆数问题
- Character set 'utf-8' is not a compiled character set and is not specified
- python mysqldb安装
- IOS网络——检测网络状态:Reachability