多线程设计模式之Future
学习这个模式先理解同步和异步的概念(这里不赘述了),核心思想就是异步调用,通俗理解就是让客户不用等你处理结果可以干其它事用着爽,所以如何解决这个问题呢,说白了就是客户是一个主线程,处理数据是一个子线程(可能不严谨,但是好理解吧?),你做你的我干我的大家阻塞不了谁最后老了一起建立和谐社会,还是放一张图吧显得专业点:
然后就是一个代码实现了,大概实现这样一个例子:自建一个逻辑类去实现一个总的逻辑,由客户端发送请求参数,然后传给Future数据类,Future数据类继续传参给RealData类异步处理。
Data接口:
public interface Data {
String getRequest();// 获取请求之后数据的方法
}
补充:以上的面向接口编程需要好好学习琢磨。
FutureData实现类:
/**
* FutureData类
*/
public class FutureData implements Data {
private RealData realData;
//set
public synchronized void set(String str) {
this.realData=new RealData();
this.realData.get(str);
notify();
}
//request
@Override
public synchronized String request() {
try {
//判断是否装载好这个realData,否则主线程会一直阻塞,这里的设置是主线程(其实也可以设置成是一个子线程,看需要了)
if(realData==null){
wait();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return realData.request();
}
}
RealData实现类:
/**
* RealData类
*/
public class RealData implements Data{
String result;
//处理数据并返回结果
public void get(String str) {
System.out.println("后台:正在处理,等待中");
try {
TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("后台:处理完毕,正在返回");
result="已获取请求,结果是"+5;
}
@Override
public String request() {
return result;
}
}
客户端类:
public class FutureClient {
//getRequest,返回一个FutureData类型,先顶着
public Data getRequest(String str){
FutureData futureData=new FutureData();
//传入参数
//这里用一个set来获取
new Thread(()->{
futureData.set(str);
}).start();
return futureData;
}
}
测试逻辑类:
public class Test {
public static void main(String[] args) {
//创建客户端
FutureClient futureClient=new FutureClient();
//传入请求参数,接收相应的返回,那么就创建一个方法
FutureData result= (FutureData) futureClient.getRequest("我的请求");
System.out.println("我发送了一个请求");
// 如果不使用 Future 模式,则阻塞等待,请求正常结束或者请求失败返回错误信息。
//继续干事情:这个阶段可以干自己的事情
System.out.println("继续做我的事情");
//获取处理结果并打印
System.out.println(result.request());
}
}
运行的结果:
这里需要说明几点感想和理解:
1、首先,以上的代码贴出来并不是很重要,重要的是如何去把握住这个模式的核心思想;其次,代码并不是边看边敲的,而是看了几遍之后,自己琢磨如何去慢慢写出来(我一开始也是纠结怎么写):先定义好接口,定好一个总思想,定义好方法,之后慢慢完善实现。
2、教程中的原代码有一点是我觉得要该进的,就是它在客户端类就创建了RealData类对象去直接给它传参,而我觉得可以把这个RealData类对象去放到FutureData中去创建和传参(也这么做了,成员变量的方式),这样FutureData类可以真正起到一个承前启后的一个功能吧?看起来也更有递进的层次感。
3、一开始对原代码的wait和notify用不明白,后来分析了一下,它们都是对同一个锁进行操作,但是一个是子线程,另一个是主线程,这里个人觉得还是需要该进的一个地方是最后的request方法应该放到子线程中,原代码是把它放进了Test这个逻辑类去顺序处理,那么假如我在做其它事情之前就访问这个方法呢?这样主线程就阻塞了,所以客户端传给测试类的不应该是futureData这个对象,而应该是一个结果,这样主线程就不会太过依赖执行的顺序了(算是一个菜鸡的理解吧,可以忽略。。)。
最后对这个Future模式感慨一下(无厘头):为什么叫future呢,因为“我们虽然只是打了个照面让彼此的感觉更为舒畅,但是你我的缘分在未来还会继续,那时才是真正的故事”。