本文主要是介绍《Java高并发程序设计》学习 --5.5 并行模式之 Future模式,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
它的核心是异步调用,如果我们不着急要结果,可以让被调用者立刻返回,随后让它在后台慢慢处理这个请求,对于调用者来说则可以处理其他任务,在真正需要数据的场合再去尝试获得需要的结果。
1)Future模式的主要角色
参与者 | 作用 |
Main | 系统启动,调用Client发出请求 |
Client | 返回Data对象,立即返回FutureData,并开始ClientThread线程装配RealData |
Data | 返回数据的接口 |
FutureData | Future数据,构造很快,但是一个虚拟的数据,需要装配RealData |
FutureRealData | 真实的数据,其构造比较慢 |
它的核心结构如图所示。
2)Future模式的简单实现
在这个实现中,有一个核心接口Data,这就是客户端希望获取的数据。在Future模式中,这个Data接口有两个重要的实现,分别是RealData,也就是真是数据,这就是我们最终需要获得的,有价值的信息。另外一个就是FutureData,它就是用来提取RealData的一个“订单”。因此FutureData是可以立即返回得到。
下面是Data接口:
public interface Data {public String getResult();
}
FutureData实现了一个快速返回的RealData包装。它只是一个包装,或者说是一个RealData的虚拟实现。因此,它可以很快被构造并返回。当使用RealData准备好并注入到FutureData中,才最终返回数据。
//FutureData是Future模式的关键,它实际上是真实数据RealData的代理,封装了获取RealData的等待过程
public class FutureData implements Data {RealData realData = null; //FutureData是RealData的封装boolean isReady = false; //是否已经准备好public synchronized void setRealData(RealData realData) {if(isReady)return;this.realData = realData;isReady = true;notifyAll(); //RealData已经被注入到FutureData中了,通知getResult()方法}@Overridepublic synchronized String getResult() throws InterruptedException {if(!isReady) {wait(); //一直等到RealData注入到FutureData中}return realData.getResult(); }
}
RealData是最终需要使用的数据模型。它的构造很慢。在这里,使用sleep()函数模拟这个过程,简单地模拟一个字符串的构造。
public class RealData implements Data {protected String data;public RealData(String data) {//利用sleep方法来表示RealData构造过程是非常缓慢的try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}this.data = data;}@Overridepublic String getResult() {return data;}
}
接下来就是我们的客户端程序,Client主要实现了获取FutureData,并开启构造RealData的线程。并在接受请求后,很快的返回FutureData。注意,它不会等待将数据真的构造完毕再返回,而是立即返回FutureData,即使这个时候FutureData并没有真实数据。
public class Client {public Data request(final String string) {final FutureData futureData = new FutureData();new Thread(new Runnable() {@Overridepublic void run() {//RealData的构建很慢,所以放在单独的线程中运行RealData realData = new RealData(string);futureData.setRealData(realData);}}).start();return futureData; //先直接返回FutureData}
}
最后,就是主函数Main,它主要负责调用Client发起请求,并消费返回的数据。
public static void main(String[] args) {Client client = new Client();Data data = client.request("name");System.out.println("请求完毕");try {Thread.sleep(2000);} catch (InterruptedException e) { }System.out.println("数据 = " + data.getResult());
}
3)JDK中的Future模式
Future模式的基本结构,其中Future接口就类似于订单或者说是契约。通过它,可以得到真实的数据。RunnableFuture继承了Future和Runnable两个接口,其中run()方法用于构造真实的数据。它有一个具体的实现FutureTask类。FutureTask有一个内部的Sync,一些实质性工作,会委托Sync类实现。而Sync类最终会调用Callable接口,完成实际数据的组装工作。
Callable()接口只有一个方法call(),它会返回需要构造的实际数据。这个Callable接口也是这个Future框架和应用程序之间的重要接口。如果我们要实现自己的业务系统,通常需要实现自己的Callable对象。此外,FutureTask类也与应用程序密切相关,通常,我们会使用Callable实例构造一个FutureTask实例,并将它提交给线程池。
下面将展示内置的Future模式的使用:
public class JRealData implements Callable<String> {private String para;public JRealData(String para) {this.para = para;}@Overridepublic String call() throws Exception {StringBuffer sb = new StringBuffer();for(int i=0; i<10; i++) {sb.append(para);try {Thread.sleep(100);} catch (InterruptedException e) {}}return sb.toString();}
}
上述代码实现了Callable接口,它的call()方法会构造我们需要的真实数据并返回。当然这个过程可以是缓慢的,这里使用Thread.sleep()模拟它:
public class FutureMain {public static void main(String[] args) throws InterruptedException, ExecutionException {FutureTask<String> future = new FutureTask<>(new JRealData("a"));ExecutorService executor = Executors.newFixedThreadPool(1);executor.submit(future);System.out.println("请求完毕");try {Thread.sleep(2000);} catch (InterruptedException e) {}System.out.println("数据 = " + future.get());}
}
上述代码就是使用Future模式的典型。第4行,构造了FutureTask对象实例,表示这个任务是有返回值的。构造FutureTask时,使用Callable接口,告诉FutureTask我们需要的数据应该如何产生。接着,第8行,将FutureTask提交给线程池。显然,作为一个简单任务的提交,这里必然是立即返回的,因此程序不会阻塞。接下来,不用关心数据是如何产生的。可以去做一些额外的事情,然后在需要的时候就可以通过Future.get()得到实际的数据。
除了基本的功能外,JDK还为Future接口提供了一些简单的控制功能:
boolean cancel(boolean mayInterruptIfRunning); //取消任务boolean isCancelled(); //是否已经取消boolean isDone(); //是否已经完成V get() throws InterruptedException,ExecutionException //取得返回对象V get(long timeout, TimeUnit unit); //取得返回对象,可以设置超时时间
注:本篇博客内容摘自《 Java 高并发程序设计》
这篇关于《Java高并发程序设计》学习 --5.5 并行模式之 Future模式的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!