Future模式,也是非常经典的设计模式,这种模式主要就利用空间换时间的概念,也就是说异步执行(需要开启一个新的线程)。
在互联网高并发的应用服务中,我们随处可见这种理念和代码,主要就是使用了这种模式!
Future模式非常适合在处理很耗时很长的业务逻辑时进行使用,可以有效的减小系统的响应时间,提高系统的吞吐量!
1/实现Callable接口
2/
3/
4/
package com.bfxy.thread.core.juc;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class UseFuture implements Callable<String> {
private String param;
public UseFuture(String param){
this.param = param;
}
@Override
public String call() throws Exception {
//模拟执行业务逻辑的耗时
Thread.sleep(3000);
String result = this.param + ", 处理完成!";
return result;
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
String queryStr1 = "query1";
String queryStr2 = "query2";
FutureTask<String> future1 = new FutureTask<String>(new UseFuture(queryStr1));
FutureTask<String> future2 = new FutureTask<String>(new UseFuture(queryStr2));
ExecutorService executorService = Executors.newFixedThreadPool(2);
executorService.submit(future1); //异步的操作
executorService.submit(future2); //异步的操作
System.err.println("处理其他相关的任务...");
Thread.sleep(2000);
String ret1 = future1.get();
String ret2 = future2.get();
//guava
System.err.println("数据处理完成: " + ret1);
System.err.println("数据处理完成: " + ret2);
}
}
模拟future
Future模式有点类似于商品订单。
比如在网购时,当看重某一件商品事,就可以提交订单,当订单处理完成后,在家里等待商品送货上门即可。
或者说更形象的我们发送Ajax请求的时候,页面是异步的进行后台处理,用户无须一直等待请求的结果,可以继续浏览或操作其他内容。
模拟代码:
package com.bfxy.thread.core.design.future;
public class Main {
public static void main(String[] args) {
FutureClient fc = new FutureClient();
Data data = fc.request("请求参数.."); //异步执行的
System.err.println("做其他的相关业务操作!");
String ret = data.getRequest(); //才是真正的获取实际数据的方法
System.err.println("--------: " + ret);
}
}
获取请求接口封装类(接口):
package com.bfxy.thread.core.design.future;
public interface Data {
String getRequest();
}
包装类实现Data接口:
package com.bfxy.thread.core.design.future;
public class FutureData implements Data {
// 真实数据对象的引用
private RealData realData;
// 实际处理的状态
private boolean isReady = false;
public synchronized void setRealData(RealData realData) {
if(isReady) {
return;
}
//如果真实对象赋值成功, 那么就认为数据已经准备好了
this.realData = realData;
isReady = true;
//真实数据已经准备好了的时候 我们进行唤醒操作
notify();
}
@Override
public synchronized String getRequest() {
while(!isReady) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return this.realData.getRequest();
}
}
真实处理数据类实现Data接口:
package com.bfxy.thread.core.design.future;
public class RealData implements Data {
private String result;
public RealData(String queryStr) {
System.err.println("根据查询参数:" + queryStr + "进行查询数据库操作, 这可能需要5秒左右...");
try {
//时间的查询耗时
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
result = "100条数据";
}
@Override
public String getRequest() {
return result;
}
}
请求类:
package com.bfxy.thread.core.design.future;
public class FutureClient {
public Data request(final String queryStr) {
FutureData futureData = new FutureData();
//异步的起一个线程去进行相应的处理
new Thread(new Runnable() {
@Override
public void run() {
//需要把请求参数 设置到真实的数据处理对象中去
RealData realData = new RealData(queryStr);
//真实请求处理完成以后, 我们要进行设置结果给包装类对象
futureData.setRealData(realData);
}
}).start();
return futureData;
}
}