Java并发编程五 Future模式
Future是并发编程中的一种设计模式,对于多线程来说,线程A需要等待线程B的结果,它没必要一直等待B,可以先拿到一个未来的Future,等B有了结果后再取真实的结果。
它的核心思想就是异步调用。当我们需要调用一个函数,但是这个函数执行很慢,如果我们不需要马上知道结果,我们可以立即返回,让它在后台慢慢处理这个请求,对于调用者来说,可以先处理一些其他任务,这个就充分利用等待时间,在真正需要数据场合再去尝试获取需要的数据。
1.Java代码实现Future模式
Future模式角色
1、Main:启动系统,调用Client发出请求;
2、Client:返回Data对象,理解返回FutureData,并开启ClientThread线程装配RealData;
3、Data:返回数据的接口;
4、FutureData:Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData;
5、RealData:真实数据,构造比较慢。
/**
* 返回Data对象,理解返回FutureData,并开启ClientThread线程装配RealData;
*
* Created by lyyz on 18-5-14.
*/
public class FutureClient {
public Data request(String params){
System.out.println("FutureClient new FutureData 对象");
final FutureData futureData = new FutureData();
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
RealData realData = new RealData(params);
futureData.setRealData(realData);
}
});
System.out.println("FutureClient 开启线程 new RealData 对象 并且将RealData装配到FutureData中 ");
thread.start();
return futureData;
}
public static void main(String[] args) {
FutureClient futureClient = new FutureClient();
Data data = futureClient.request("1+1 ");
System.out.println("Main 通过FutureClient对象发送完请求 继续总其他事情");
System.out.println(data.getData());
}
}
/**
* 返回数据的接口;RealData和FutureData都需要实现Data接口(装饰器模式)
* Created by lyyz on 18-5-14.
*/
public interface Data {
/**
* 得到数据方法
* @return
*/
String getData();
}
/**
* Future数据,构造很快,但是是一个虚拟的数据,需要装配RealData;
*
* Created by lyyz on 18-5-14.
*/
public class FutureData implements Data {
private RealData realData;
private boolean isFinish;
public FutureData(){
isFinish = false;
}
public synchronized void setRealData(RealData realData){
System.out.println("FutureData 装配RealData对象 ");
if(isFinish){
return;
}
this.realData =realData;
this.isFinish = true;
notify();
}
@Override
public synchronized String getData() {
System.out.println("FutureData 调用RealData对象的 getData方法 返回真实数据 ");
if(!isFinish){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return this.realData.getData();
}
}
/**
* 真实数据,构造比较慢。
*
* Created by lyyz on 18-5-14.
*/
public class RealData implements Data {
//请求参数
private String requestParams;
//返回结果
private String result;
public RealData(String requestParams) {
this.requestParams = requestParams;
}
@Override
public String getData() {
try {
System.out.println("RealData:真实的请求方法 start");
Thread.sleep(5000);
result = "参数为:"+requestParams+" 请求结果为 2";
System.out.println("RealData:真实的请求方法 end");
} catch (InterruptedException e) {
e.printStackTrace();
}
return result;
}
}
2. java.util.concurrent包提供的Future接口
Jdk并发包下也提供了Future模式。直接使用就可以了。
1. Future接口其实现类为FutureTask (相当与FutureData)
2. 还有Callable接口 (相当与 RealData)
用Jdk提供的Future和Callable实现Future模式非常简单。
/**
* Created by lyyz on 18-5-14.
*/
public class FutureTest_eg {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newSingleThreadExecutor();
//向线程池提交callable实现类,会立即返回一个 FutureTask 实例对象
Future futureTask = executorService.submit(new CallableTest());
System.out.println(futureTask.hashCode());
System.out.println("阻塞等待");
//当通过futureTask实例调用get()方法时,会阻塞等待,直到callable的run()方法执行完毕,返回真是结果
System.out.println(futureTask.get());
executorService.shutdown();
}
}
class CallableTest implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(5000);
return "aa";
}
}