概述:
Futrue模式:对于多线程,如果线程A要等待线程B的结果,那么线程A没必要等待B,直到B有结果,可以先拿到一个未来的Future,等B有结果是再取真实的结果。
主要角色:
- Client:发出请求
- Server:返回Data对象,立即返回FutureData,并开启Thread线程装配RealData
- Data:返回数据的接口
- FutureData:Futrue数据,是一个虚拟的数据,需要装配RealData
- RealData:真实数据,构造比较慢
时序图:
演示代码:
public interface Data {
String getRequest();
}
public class RealData implements Data {
private String result;
public RealData(String request) {
System.out.println("根据" + request + "进行查询..,要花很久时间");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("操作完毕,获取结果");
result = "查询结果";
}
public String getRequest() {
return result;
}
}
public class FutureData implements Data {
private RealData realData;
private boolean isReady = false;
public synchronized String getRequest() {
while (!isReady) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
return this.realData.getRequest();
}
public synchronized void setRealData(RealData realData) {
if (isReady) {
return;
}
this.realData = realData;
isReady = true;
notify();
}
}
public class FutureClient {
public Data request(final String request) {
final FutureData futureData = new FutureData();
// 开启线程执行操作
new Thread(new Runnable() {
public void run() {
RealData realData = new RealData(request);
futureData.setRealData(realData);
}
}).start();
return futureData;
}
}
public class Main {
public static void main(String[] args) {
FutureClient fClient = new FutureClient();
Data data = fClient.request("hello,world");
System.out.println("请求发送成功...");
System.out.println("干其他的事情...");
String result = data.getRequest();
System.out.println(result);
}
}
JDK实现:
import java.util.concurrent.Callable;
public class RealData implements Callable<String> {
private String param;
public RealData(String param) {
this.param = param;
}
// 处理业务逻辑
public String call() throws Exception {
//利用sleep来表示任务处理
Thread.sleep(2000);
return "这是根据"+param+"处理后返回的结果";
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
public class Main {
public static void main(String[] args) throws Exception {
Long start = System.currentTimeMillis();
FutureTask<String> futureTask = new FutureTask<>(new RealData("hello,world"));
ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(1);
newFixedThreadPool.submit(futureTask);
// 表示主线程正在处理其他逻辑,或者业务
Thread.sleep(1000);
System.out.println("子线程处理完成后的结果-->" + futureTask.get());
Long end = System.currentTimeMillis();
Long useTime = end - start;
System.out.println("程序运行了-->" + useTime + "毫秒");
}
}
补充
1、并发编程时,一般使用Runnable,然后扔给线程池就完事,这种情况下不需要线程的结果。 所以run的返回值是void类型。
2、如果是一个多线程协作程序,比如菲波拉切数列:1,1,2,3,5,8…使用多线程来计算。 但后者需要前者的结果,就需要用Callable接口了。
3、Callable用法和Runnable一样,只不过调用的是call方法,该方法有一个泛型返回值类型,你可以任意指定。
4、线程是属于异步计算模型,所以你不可能直接从别的线程中得到函数返回值。这时候,Future就出场了。Futrue可以监视目标线程调用call的情况,当你调用Future的get()方法以获得结果时,当前线程就开始阻塞,直接call方法结束返回结果。