一步步学习java并发编程模式之Active Object模式(三)java实现active object

来源:互联网 发布:js格式化时间戳format 编辑:程序博客网 时间:2024/06/05 03:17

      现在我们已经知道active object模式的核心思想,也明白了如何自己写一段实现类似效果的java代码。现在我们按照active object模式的角色分工,将第二篇中的例子重新实现下,参考了Active Object并发模式在Java中的应用 这篇博客。在 Active Object 模式中,主要有以下几种类型的参与者:

  • 代理 (proxy) :代理是 Active Object 所定义的对于调用者的公共接口。运行时,代理运行在调用者线程的上下文中,负责把调用者的方法调用转换成相应的方法请求 (Method Request),并将其插入相应的 Activation List,最后返回给调用者 Future 对象。代理角色具有以下几个特点:
        1.proxy和servant有着相同的接口签名,或者proxy比servant接口更简单好用。这样可以方便调用者无差别的对待proxy和servant,或者更容易使用代理
        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 方法执行的结果。

我们现在先编写servant类,这个是整个active object角色中最简单的
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;    }}

到这里我们的请求已经在activation 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() {@Overridepublic 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实现。

1 0