多线程设计模式 - Future模式
并发设计模式属于设计优化的一部分,它对于一些常用的多线程结构的总结和抽象。与串行相比并行程序结构通常较为复杂,因此合理的使用并行模式在多线程并发中更具有意义。
1. Future
Future模式是多线程开发中非常常见的一种设计模式,它的核心思想是异步调用。
这类似我们日常生活中的在线购物流程,带在购物网看着一件商品时可以提交表单,当订单完成后就可以在家里等待商品送货上门。
或者说更形象的是我们发送Ajax请求的时候,页面是异步的进行后台处理,用户无需等待请求的结果,可以继续浏览或操作其他内容
示例:下面示例为Future的原理实现;<br />
说明:看类注释即可明了 不明白可以去屎
1 //Data.java * 首先看这个接口Data,只有一个方法getRequest(),返回String字符串. 2 public interface Data { 3 String getRequest(); 4 } 5 //RealData.java * 然后再看RealData这个类,实现了Data接口,首先他有构造函数,可以理解为一个真实的业务逻辑,比较耗时,做这个sleep我们可以想象成在处理业务逻辑. 6 public class RealData implements Data{ 7 private String result; 8 9 public RealData(String queryStr){ 10 System.out.println("根据"+queryStr+"进行查询,这是一个很耗时的操作.."); 11 try { 12 Thread.sleep(5000); 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 System.out.println("操作完毕,获取结果"); 17 result="查询结果"; 18 } 19 20 @Override 21 public String getRequest() { 22 return result; 23 } 24 } 25 26 //FutureData.java* 接着再看FutureData这个类,也实现了Data接口.先看FutureData的getRequest()方法,这个方法先死循环判断boolean,如果isReady是true,就阻塞着,不然就返回RealData真的getRequest()\方法(真实的结果). 27 // 然后再看setRealData(),判断isReady,如果是ture,直接return,如果不是就赋值RealData,并修改isReady,然后notify().. 28 public class FutureData implements Data{ 29 30 private RealData realData; 31 private boolean isReady = false; 32 33 public synchronized void setRealData(RealData realData){ 34 //如果已经加载完毕就直接返回 35 if(isReady){ 36 return; 37 } 38 //如果没有装载,进行装载真实对象 39 this.realData= realData; 40 isReady = true; 41 //进行通知 42 notify(); 43 } 44 45 @Override 46 public synchronized String getRequest() { 47 //如果没有装载好,程序就一直处于阻塞状态 48 while(!isReady){ 49 try { 50 wait(); 51 } catch (InterruptedException e) { 52 e.printStackTrace(); 53 } 54 } 55 //装载好直接获取数据即可 56 return this.realData.getRequest(); 57 } 58 } 59 //FutureClient.java * 最后看FutureClient 这个类,最简单了,返回futureData,偷偷开了线程,看到RealData realData = new RealData(request)没有?就是开始执行业务了,然后当FutureData这个类的setRealData(RealData realData)时就通知了.. 60 public class FutureClient { 61 62 public Data request(final String queryStr){ 63 //1 我想要一个代理对象(Data接口的实现类)先返回发送请求的客户端,告诉他请求已经接收到,可以做其他事情 64 final FutureData futureData = new FutureData(); 65 //2 启动一个新的线程,去加载真实的数据,传递给这个代理对象 66 new Thread(new Runnable(){ 67 @Override 68 public void run() { 69 //3 这个新的线程可以去慢慢加载真实对象,然后传递给代理对象 70 RealData realData = new RealData(queryStr); 71 futureData.setRealData(realData); 72 } 73 }).start(); 74 //直接返回一个假的包装类futureData 75 return futureData; 76 } 77 } 78 //主函数 79 public class Main { 80 81 public static void main(String[] args) { 82 FutureClient fc = new FutureClient(); 83 Data data = fc.request("请求参数"); 84 System.out.println("请求发送成功!"); 85 System.out.println("做其他的事情..."); 86 87 String result = data.getRequest(); 88 System.out.println(result); 89 } 90 }
上面的原理你可以不用懂,当然懂最好了,可以在面试官面前吹牛逼啊..future模式这么凶残,jdk也有实现的,在java.util.concurrent,又是concurrent,这个工具类真的是强大<br />
示例:<br />
1 // 2 import java.util.concurrent.Callable; 3 4 public class RealData implements Callable<String> { 5 private String Data; 6 7 public RealData(String Data) { 8 this.Data = Data; 9 } 10 11 public String call() throws Exception { 12 //利用sleep来表示任务处理 13 Thread.sleep(2000); 14 15 return "这是处理"+Data+"结果"; 16 } 17 } 18 // 19 import java.util.concurrent.ExecutorService; 20 import java.util.concurrent.Executors; 21 import java.util.concurrent.FutureTask; 22 23 public class Main { 24 25 public static void main(String[] args) throws Exception { 26 Long start = System.currentTimeMillis(); 27 28 FutureTask<String> futureTask = new FutureTask<>(new RealData("hello,world")); 29 ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(1); 30 newFixedThreadPool.submit(futureTask); 31 32 // 表示正在处理其他逻辑,或者业务 33 Thread.sleep(1000); 34 35 System.out.println("最后结果-->" + futureTask.get()); 36 37 Long end = System.currentTimeMillis(); 38 39 Long useTime = end - start; 40 41 System.out.println("程序运行了-->" + useTime + "毫秒"); 42 } 43 }