上一篇博客一步步学习java并发编程模式之Active Object模式(一)中介绍了Active Object的一些思想和作用,这篇文章打算自己写1个简单的模拟Active Object的例子。
假设有一个天气预报计算服务,见以下代码:
package activeobject.aty; // 模拟天气预报的查询结果 // 今日天气实况:气温: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 + "]"; } }
package activeobject.aty.service; import activeobject.aty.WeatherResult; public class WeatherService { public static 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; } }
下面是测试代码,进行常规的同步方法调用:
public static void testSyncCall() { // 1.调用天气计算服务,开始计算深圳的天气情况(开始计算) WeatherResult info = WeatherService.getWeatherInfo("广东深圳", "2014-03-14"); System.out.println("After calling weather service,i was blocked."); System.out.println("Now,i really need weather result to continue."); System.out.println("天气查询结果:" + info); }
如果计算天气服务不执行完毕,后续的打印代码是不会执行的,而这些代码实际上是不依赖于天气计算结果的,显然并发执行差。下面我们采取异步调用的方式来解决这个问题。
package activeobject.aty.proxy; import activeobject.aty.call.EvaluateWeatherTask; import activeobject.aty.future.WeatherFuture; public class WeatherProxy { public static WeatherFuture getWeatherInfo(String city, String day) { WeatherFuture future = new WeatherFuture(); new Thread(new EvaluateWeatherTask(future, city, day)).start(); return future; }
package activeobject.aty.service; import activeobject.aty.WeatherResult; import activeobject.aty.future.WeatherFuture; public class EvaluateWeatherTask implements Runnable { private WeatherFuture future; private String city; private String day; public EvaluateWeatherTask(WeatherFuture future, String city, String day) { this.future = future; this.city = city; this.day = day; } @Override public void run() { WeatherResult r = WeatherService.getWeatherInfo(city, day); future.setResult(r); future.setDone(true); } }
package activeobject.aty.future; import activeobject.aty.WeatherResult; 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; } }
下面是测试代码
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); }