Future模式是一个多线程的设计模式,以下一个简单的实现例子。
实现的原理有点类似订蛋糕,你去商店定做蛋糕时,并不能直接拿到蛋糕,而是拿到购物小票之类的,你需要等蛋糕制作完成后,再来取。在这期间你可以去做其他的事情,而不必在蛋糕店等待蛋糕的制作。这和单独开一个线程没有什么区别,具体有什么好处我目前也不是很清楚,能感受到的就是代码更加简洁了..易读性增强了吧~
/**
* Created by Anur IjuoKaruKas on 2017/10/6.
* Description :
*/
public class Main {
public static void main(String[] args) {
PeopleFutureClient peopleFutureClient = new PeopleFutureClient();
PeopleFutureContainer peopleFutureContainer = peopleFutureClient.getPeopleFutureContainer("Anur", "女");
System.out.println(Thread.currentThread().getName() + ": 执行接下去的业务");
System.out.println(Thread.currentThread().getName() + ": " + peopleFutureContainer.getPeople());
}
}
我们先去蛋糕店,
PeopleFutureClient peopleFutureClient = new PeopleFutureClient();
拿到一张购物小票,店员我们需要一个什么什么样的蛋糕,这个peopleFutureContainer就是一个购物小票。
PeopleFutureContainer peopleFutureContainer = peopleFutureClient.getPeopleFutureContainer("Anur", "女");
然后我们就可以撤了,明天凭购物小票peopleFutureContainer再来拿(getPeople())。
System.out.println(Thread.currentThread().getName() + ": 执行接下去的业务");
System.out.println(Thread.currentThread().getName() + peopleFutureContainer.getPeople());
很多网上的例子都是一个接口,然后各种RealData,FutureData,总觉得不是很有必要那么写。
下面是我自己的实现方式:
/**
* Created by Anur IjuoKaruKas on 2017/10/6.
* Description :
*/
public class PeopleFutureClient {
public PeopleFutureContainer getPeopleFutureContainer(String name, String sex) {
PeopleFutureContainer peopleFutureContainer = new PeopleFutureContainer();
new Thread(new Runnable() {
@Override
public void run() {
peopleFutureContainer.setPeople(new People(name, sex));
}
}, "获取信息的线程").start();
return peopleFutureContainer;
}
}
蛋糕店,里面就一个取小票的方法
这里直接new了一个小票,并在线程中去执行做蛋糕的方法setPeople,并直接返回了小票。
/**
* Created by Anur IjuoKaruKas on 2017/10/6.
* Description :
*/
public class PeopleFutureContainer {
private People people;
private boolean isReady = false;
public synchronized void setPeople(People people) {
StringBuffer sout = new StringBuffer(Thread.currentThread().getName() + ": 获取信息中");
try {
for (int i = 0; i < 5; i++) {
Thread.sleep(1000);
System.out.println(sout);
sout.append(".");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ": 获取完成");
this.people = people;
isReady = true;
notify();
}
public synchronized People getPeople() {
if (!isReady) {
try {
System.out.println(Thread.currentThread().getName() + ": 准备获取信息");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return people;
}
}
小票的规则也很简单,就一个set,一个get,都加了锁,这个小票中有一个状态标记isReady,这个的作用相当于电话,你如果没有接到蛋糕店的电话就去取蛋糕了(getPeople),去了以后蛋糕店会告诉你,蛋糕还没做完,等着吧(wait())。等蛋糕做完你才能取走。(比喻不是特别恰当)
当然如果你是等蛋糕做完才来的,那么直接取走就行了,因为这个时候,isReady 已经是ture了,并不需要wait()。
main: 执行接下去的业务
main: 准备获取信息
获取信息的线程: 获取信息中
获取信息的线程: 获取信息中.
获取信息的线程: 获取信息中..
获取信息的线程: 获取信息中...
获取信息的线程: 获取信息中....
获取信息的线程: 获取完成
main: 姓名:Anur,性别:女
执行结果,显而易见,我们来早了,所以“main: 准备获取信息”,蛋糕店让我们等着,过了一会儿,我们取到了蛋糕。
想了一下突然发现这样写不如原来的…自己写的这个不符合开放-封闭原则。
2017/10/10补充:
在jdk的Concurrent包中已经有了实现了future模式的类
final ExecutorService executorService = Executors.newFixedThreadPool(5);
Callable callable = (() -> {
System.out.println("请求发送");
RealData realData = new RealData();
return realData.getRequest();
});
Future future = executorService.submit(callable);
System.out.println("正在做其他事情");
String result = (String) future.get();
System.out.println(result);
executorService.shutdown();
只需要new一个ExecutorService,然后再Callable中去new一个对象并返回,第三步是new一个Future = executorService.submig(callable)
在需要的时候调用future.get方法即可。
最后不要忘记将ExecutorService关闭掉。
正在做其他事情
请求发送
耗时操作
时间============0
时间============1
时间============2
时间============3
时间============4
操作完毕
查询结果
打印结果。