Future模式就是,当某一程序提交请求,指望获得一个答复。可是可能服务器程序对这个请求的处理比较慢,所以不可能立刻收到答复。可是,在传统的单线程环境下,调用函数是同步的,它必须等到服务程序返回结果,才能继续进行其余处理。而Future模式下,调用方法是异步的,本来等待返回的时间段,在主调函数中,则能够处理其余的任务。传统的串行程序以下图所示:html
Future模式的处理流程:java
从图中能够看出,虽然call()自己是一个须要很长世间处理的程序。可是,服务程序不等数据处理完就马上返回客户端一个伪数据,实现Future模式的客户端在拿到这个返回结果后,并不急于对它进行处理,而是去调用其它的业务逻辑,使call()方法有充分的时间去处理完成,这也是Future模式的精髓所在。 在处理完其余业务逻辑后,最后再使用处理比较费时的Future数据。这个在处理过程当中,就不存在无谓的等待,充分利用了时间,从而提高了系统的响应和性能。web
下面以一个经典的Future实现为例,简单介绍下Future的核心实现。代码中服务器
public interface Data { public String getResult(); } public class FutureData implements Data { protected RealData realData = null; protected boolean isReady = false; //进行同步控制 public synchronized void setResult(RealData realData){ if(isReady){ return; } System.out.println("FutureData.setResult()"); this.realData=realData; isReady = true; notifyAll(); } //实际调用返回RealDate的数据 @Override public synchronized String getResult() { while(!isReady){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("FutureData.getResult()"); return realData.result; } public class RealData implements Data{ protected final String result; public RealData(String s) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < 10; i++) { sb.append(s); try { //模拟构造时间比较长 Thread.sleep(1000); } catch (InterruptedException e) { } } System.out.println("RealData.RealData()"); result = sb.toString(); } public class Client { public Data request(final String queryStr){ //返回伪数据 final FutureData futureData = new FutureData(); //开启线程构造真实数据 new Thread(){ public void run(){ RealData realData = new RealData(queryStr); futureData.setResult(realData); } }.start(); //返回伪数据,等待真实数据加载 return futureData; } }
public interface Data { public String getResult(); } public class FutureData implements Data { protected RealData realData = null; protected boolean isReady = false; //进行同步控制 public synchronized void setResult(RealData realData){ if(isReady){ return; } System.out.println("FutureData.setResult()"); this.realData=realData; isReady = true; notifyAll(); } //实际调用返回RealDate的数据 @Override public synchronized String getResult() { while(!isReady){ try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("FutureData.getResult()"); return realData.result; } public class RealData implements Data{ protected final String result; public RealData(String s) { StringBuffer sb = new StringBuffer(); for (int i = 0; i < 10; i++) { sb.append(s); try { //模拟构造时间比较长 Thread.sleep(1000); } catch (InterruptedException e) { } } System.out.println("RealData.RealData()"); result = sb.toString(); } public class Client { public Data request(final String queryStr){ //返回伪数据 final FutureData futureData = new FutureData(); //开启线程构造真实数据 new Thread(){ public void run(){ RealData realData = new RealData(queryStr); futureData.setResult(realData); } }.start(); //返回伪数据,等待真实数据加载 return futureData; } }
启动系统,调用Client发送请求:并发
public class TestMain { public static void main(String[] args) { Data data = new Client().request("123456"); System.out.println(data); System.out.println(data.getResult()); } }
public class TestMain { public static void main(String[] args) { Data data = new Client().request("123456"); System.out.println(data); System.out.println(data.getResult()); } }
能够看出,FutureData是Future模式实现的关键,它实际是真实数据RealData的代理,封装了获取RealDate的等待过程.app
在JDK的内置并发包中,就已经内置了一种Future的实现,提供了更加丰富的线程控制,其基本用意和核心理念与上面实现代码一致。异步
在JDK中的Future模式中,最重要的是FutureTask类,它实现了Runnable接口,能够做为单独的线程运行。在其run()方法中,经过Sync内部类,调用Callable接口,并维护Callable接口的返回对象。当使用FutureTask.get()时,将返回Callable接口的返回对象。FutureTask还能够对任务自己进行其余控制操做。ide
利用Callable接口实现上述例子相同的操做:svg
RealData类的实现:函数
public class Real1Data implements Callable<String>{ private String reaString; public Real1Data(String reaString) { super(); this.reaString = reaString; } @Override public String call() throws Exception { StringBuffer sb = new StringBuffer(); for (int i = 0; i < 10; i++) { sb.append(reaString); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO: handle exception } } return sb.toString(); } }
public class Real1Data implements Callable<String>{ private String reaString; public Real1Data(String reaString) { super(); this.reaString = reaString; } @Override public String call() throws Exception { StringBuffer sb = new StringBuffer(); for (int i = 0; i < 10; i++) { sb.append(reaString); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO: handle exception } } return sb.toString(); } }
Client代码实现:
public class Test1Main { public static void main(String[] args) throws InterruptedException, ExecutionException { FutureTask<String> future = new FutureTask<>(new Real1Data("1111")); ExecutorService exe = Executors.newFixedThreadPool(1); exe.submit(future); System.out.println("FutureTask"); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("FutureTask"+future.get()); } }
public class Test1Main { public static void main(String[] args) throws InterruptedException, ExecutionException { FutureTask<String> future = new FutureTask<>(new Real1Data("1111")); ExecutorService exe = Executors.newFixedThreadPool(1); exe.submit(future); System.out.println("FutureTask"); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("FutureTask"+future.get()); } }
能够看出RealData的构造速度很快,其核心代码逻辑放在了call()中实现,再也不须要Data和FutureData,直接经过RealData来构造FutureTask,将其做为单独的线程运行。在提交请求后,执行其余业务逻辑,作好经过FututeTask.get()方法,获得RealData的执行结果。
Future模式核心在于去除了主调用函数的等待时间,并使得本来须要等待的时间能够充分利用来处理其余业务逻辑,充分的利用了系统资源。
参考:
http://www.javashuo.com/article/p-sydbtsov-bn.html
https://www.jianshu.com/p/949d44f3d9e3