一步步学习java并发编程模式之Active Object模式(三)java实现active object
现在我们已经知道active object模式的核心思想,也明白了如何自己写一段实现类似效果的java代码。现在我们按照active object模式的角色分工,将第二篇中的例子重新实现下,参考了Active Object并发模式在Java中的应用 这篇博客。在 Active Object 模式中,主要有以下几种类型的参与者:
- 代理 (proxy) :代理是 Active Object 所定义的对于调用者的公共接口。运行时,代理运行在调用者线程的上下文中,负责把调用者的方法调用转换成相应的方法请求 (Method Request),并将其插入相应的 Activation List,最后返回给调用者 Future 对象。代理角色具有以下几个特点:
2.创建client需要的future对象,并快速返回,避免调用者线程长时间等待.客户端可以通过future对象获取实际的运算结果
3.将调用者的方法调用转换成相应的方法请求 (Method Request),将request和servant传给scheduler进行调度执行
4.代理是运行在调用者线程中的,它对原始的耗时服务进行了封装,让客户端无差异的使用代理和真实对象,除了更快.
- 方法请求(method request):方法请求定义了方法执行所需要的上下文信息,诸如调用参数等。
- activation list:负责存储所有由代理创建的,等待执行的方法请求。从运行时来看,Activation List 会被包括调用者线程及其 Active Object 线程并发存取访问,所以,Activation List 实现应当是线程安全的。
- 调度者 (scheduler):调度者运行在 Active Object 线程中,调度者来决定下一个执行的方法请求,而调度策略可以基于很多种标准,比如根据方法请求被插入的顺序 FIFO 或者 LIFO,比如根据方法请求的优先级等等。
- servant::Servant 定义了 Active Object 的行为和状态,它是 Proxy 所定义的接口的事实实现。
- future:调用者调用 Proxy 所定义的方法,获得 Future 对象。调用者可以从该 Future 对象获得方法执行的最终结果。在真实的实现里,Future 对象会保留一个私有的空间,用来存放 Servant 方法执行的结果。
package activeobject.aty.servant; import activeobject.aty.result.WeatherResult; //Servant 的实现是纯粹的应用逻辑实现,或者称为商业逻辑实现,没有混合任何的线程同步机制 , 这有利于我们进行应用逻辑的重用,而不需要考虑不同的线程同步机制。 public class WeatherServant { public WeatherResult getWeatherInfo(String city, String day) { try { // 模拟耗时操作,调用该方法的线程,要挂起5s Thread.sleep(5 * 1000); } catch (InterruptedException e) { } WeatherResult result = new WeatherResult(); result.setTemperature(28); result.setWindDirection("西北风"); result.setDampness("74%"); return result; } }
package activeobject.aty.result; // 模拟天气预报的查询结果 //今日天气实况:气温:4℃;风向/风力:西北风 1级;湿度:74%;空气质量:中;紫外线强度:最弱 public class WeatherResult { // 气温 private int temperature; // 湿度 private String dampness; // 风向 private String windDirection; public int getTemperature() { return temperature; } public void setTemperature(int temperature) { this.temperature = temperature; } public String getDampness() { return dampness; } public void setDampness(String dampness) { this.dampness = dampness; } public String getWindDirection() { return windDirection; } public void setWindDirection(String windDirection) { this.windDirection = windDirection; } @Override public String toString() { return "WeatherResult [temperature=" + temperature + ", dampness=" + dampness + ", windDirection=" + windDirection + "]"; } }
现在编写methodrequest和future代码
package activeobject.aty.future; import activeobject.aty.result.WeatherResult; // 调用者调用 Proxy 所定义的方法,获得 Futur 对象。调用者可以从该 Future 对象获得方法执行的最终结果。 // 在真实的实现里,Future 对象会保留一个私有的空间,用来存放 Servant 方法执行的结果。 public class WeatherFuture { private boolean isDone = false; private WeatherResult result = null; public WeatherResult get() { while (!isDone) { } return result; } public void setDone(boolean isDone) { this.isDone = isDone; } public void setResult(WeatherResult result) { this.result = result; } }
package activeobject.aty.methodrequest; import activeobject.aty.future.WeatherFuture; import activeobject.aty.result.WeatherResult; import activeobject.aty.servant.WeatherServant; // Method Request:方法请求定义了方法执行所需要的上下文信息,诸如调用参数、返回结果和实际的服务等 public class WeatherMethodRequest { private WeatherFuture future; private WeatherServant servant; private String city; private String day; public WeatherMethodRequest(WeatherFuture future, WeatherServant servant, String city, String day) { this.future = future; this.servant = servant; this.city = city; this.day = day; } public void call() { WeatherResult result = servant.getWeatherInfo(city, day); future.setResult(result); future.setDone(true); } }
下面编写activation list
package activeobject.aty.activationlist; import java.util.ArrayList; import java.util.List; import activeobject.aty.methodrequest.WeatherMethodRequest; // Activation List 负责存储所有由代理创建的,等待执行的方法请求。 // 从运行时来看,Activation List 会被包括调用者线程及其 Active Object线程并发存取访问,所以Activation List 实现应当是线程安全的. // Activation List 的实际上就是一个线程同步机制保护下的 Method Request队列,对该队列的所有操作 (insert/remove)都应该是线程安全的。 // 从本质上讲,Activation List 所基于的就是典型的生产者 / 消费者并发编程模型,调用者线程作为生产者把 // Method Request放入该队列,Active Object 线程作为消费者从该队列拿出 Method Request, 并执行。 public class WeatherActivationList { private List<WeatherMethodRequest> requestList = new ArrayList<WeatherMethodRequest>(); public synchronized void insertTask(WeatherMethodRequest request) { requestList.add(request); } public synchronized void removeTask(WeatherMethodRequest request) { requestList.remove(request); } public synchronized boolean isEmpty() { return requestList.size() == 0; } public synchronized WeatherMethodRequest popFirst() { WeatherMethodRequest e = requestList.get(0); requestList.remove(0); return e; } }
到这里我们的请求已经在activatio list中了,我们可以基于activation list编写我们的scheduler实现
package activeobject.aty.scheduler; import activeobject.aty.activationlist.WeatherActivationList; import activeobject.aty.methodrequest.WeatherMethodRequest; // Active Object 的线程 public class WeatherStartThread implements Runnable { private WeatherActivationList safeRequestList; public WeatherStartThread(WeatherActivationList safeRequestList) { this.safeRequestList = safeRequestList; } @Override public void run() { while (true) { if (!safeRequestList.isEmpty()) { WeatherMethodRequest request = safeRequestList.popFirst(); request.call(); } } } }
package activeobject.aty.scheduler; import activeobject.aty.activationlist.WeatherActivationList; import activeobject.aty.methodrequest.WeatherMethodRequest; // scheduler:调度者运行在 Active Object线程中,调度者来决定下一个执行的方法请求, // 而调度策略可以基于很多种标准,比如根据方法请求被插入的顺序 FIFO 或者 LIFO,比如根据方法请求的优先级等等。 public class WeatherTaskScheduler { private WeatherActivationList safeRequestList = new WeatherActivationList(); public WeatherTaskScheduler() { new Thread(new WeatherStartThread(safeRequestList)).start(); } public void insertRequest(WeatherMethodRequest methodRequest) { safeRequestList.insertTask(methodRequest); } }
下面我们来编写代理类的实现,这个是客户端直接使用的类
package activeobject.aty.proxy; import activeobject.aty.future.WeatherFuture; import activeobject.aty.methodrequest.WeatherMethodRequest; import activeobject.aty.scheduler.WeatherTaskScheduler; import activeobject.aty.servant.WeatherServant; //代理 (Proxy)负责以下功能: // 1.proxy和servant有着相同的接口签名,或者proxy比servant接口更简单好用。这样可以方便调用者无差别的对待proxy和servant,或者更容易使用代理 // 2.创建client需要的future对象,并快速返回,避免调用者线程长时间等待.客户端可以通过future对象获取实际的运算结果 // 3.将调用者的方法调用转换成相应的方法请求 (Method Request),将request和servant传给scheduler进行调度执行 // 4.代理是运行在调用者线程中的,它对原始的耗时服务进行了封装,让客户端无差异的使用代理和真实对象,除了更快. public class WeatherProxy { // 对任务进行调度 private static WeatherTaskScheduler scheduler = new WeatherTaskScheduler(); // 服务的真正实现 private static WeatherServant servant = new WeatherServant(); public static WeatherFuture getWeatherInfo(String city, String day) { WeatherFuture futureResult = new WeatherFuture(); WeatherMethodRequest request = new WeatherMethodRequest(futureResult, servant, city, day); scheduler.insertRequest(request); return futureResult; } }
最后我们编写测试类,来验证我们的功能。
package activeobject.aty; import activeobject.aty.future.WeatherFuture; import activeobject.aty.proxy.WeatherProxy; import activeobject.aty.result.WeatherResult; public class TestWeather { public static void main(String[] args) throws Exception { mockMultiCall(); testAsyncCall(); } public static void testAsyncCall() throws Exception { // 1.调用天气计算服务,开始计算深圳的天气情况(开始计算) WeatherFuture future = WeatherProxy .getWeatherInfo("广东深圳", "2014-03-14"); // 2.后台在计算天气服务中.当前线程没有阻塞,仍然可以继续执行. System.out.println("After calling weather service,i am still running."); // 3.The current thread is not blocked, do something else here... // Thread.sleep(5 * 1000); // 4.与天气计算结果无关的代码执行完毕. System.out.println("Now,i really need weather result to continue."); // 5.如果计算天气还没有结束,那么当前线程挂起,等候计算完成. WeatherResult info = future.get(); System.out.println("天气查询结果:" + info); } public static void mockMultiCall() { Thread t = new Thread(new Runnable() { @Override public void run() { while (true) { long time = System.currentTimeMillis(); System.out.println("构造一个服务调用请求:"); WeatherFuture future = WeatherProxy.getWeatherInfo("广东深圳" + time, "2014-03-14"); WeatherResult info = future.get(); System.out.println("mockMultiCall结果:" + info); System.out.println(); System.out.println(); } } }); t.start(); } }
这样我们就按照active object模式的各个参与者及职责完成了java实现。
一步步学习java并发编程模式之Active Object模式(三)java实现active object,古老的榕树,5-wow.com
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。