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

      现在我们已经知道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;
    }
}

到这里我们的请求已经在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

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。