Future模式
Future介绍
Future的意思是未来。如果某个方法需要很长时间来运行,那么调用者就没有必要一直等待结果,相反,它可以先获得一个关于结果的凭证,然后等一段时间后再根据凭证来索取结果。当然,Future模式和Thread Per Message很类似,但它们的区别也很明显:一个没有返回值,一个为返回值而生。
Future使用场景
- 提高响应性、缩短延迟时间;当一项任务的处理时间远大于线程启动时间,那么就可以应用该模式来提高响应性;
- 适用于操作顺序没有要求时;每个线程执行任务结束的顺序并不一定是接收到请求的顺序;该模式只适合在对操作开始或者完成的顺序没有要求的场景下;
- 需要返回值,但是返回值的获得需要耗费很长时间;
Future示例代码分析
//返回值接口
public interface Data {
String getContent();
}
//未来获取结果的凭证
public class FutureData implements Data {
private RealData realData=null;
private boolean ready=false;
public synchronized void setRealData(RealData realData){
if(ready){
return;
}
this.realData=realData;
this.ready=true;
notifyAll();
}
public synchronized String getContent(){
while(!ready){
try{
wait();
}catch(InterruptedException e){
e.printStackTrace();
}
}
return realData.getContent();
}
}
//真实数据
public class RealData implements Data{
private final String content;
public RealData(int count,char c){
System.out.println(" making RealData("+count+","+c+") BEGIN");
char[] buffer=new char[count];
for(int i=0;i<count;i++){
buffer[i]=c;
try{
Thread.sleep(100);
}catch(InterruptedException e){
e.printStackTrace();
}
}
System.out.println(" making ReadData("+count+","+c+") END");
this.content=new String(buffer);
}
public String getContent(){
return content;
}
}
//请求处理者,为请求返回FutureData
public class Host {
public Data request(final int count,final char c){
System.out.println(" Request("+count+","+c+") BEGIN");
final FutureData futureData=new FutureData();
new Thread(){
public void run(){
RealData realData=new RealData(count,c);
futureData.setRealData(realData);
}
}.start();
System.out.println(" request("+count+","+c+") END");
return futureData;
}
}
//Tester
public class Tester {
public static void main(String[] args){
System.out.println("Main Begins");
Host host=new Host();
Data data1=host.request(10,'A');
Data data2=host.request(20,'B');
Data data3=host.request(30,'C');
System.out.println("Main otherJob BEGIN");
try{
Thread.sleep(2000);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println("Main otherJob END");
System.out.println("Data 1="+data1.getContent());
System.out.println("Data 2="+data2.getContent());
System.out.println("Data 3="+data3.getContent());
}
}
Future模式的理解
Future模式里有Thread Per Message的理念,同时在FutureData类的getContent()方法中使用了Guarded Suspension模式;
在Worker Thread模式的理解一节中,我们说该模式实现了调用和执行的分离;Future模式则实现了“准备返回值”和“使用返回值”的分离:这两个动作分别在不同的线程中完成;
使用多线程编程后,伴随着方法调用的一连串处理被分解:启动、执行、准备返回值、使用返回值,它们被交给不同的线程处理;
使用Future模式无疑提高了程序的响应性;
另外,程序中尽量不要用System.out来完成日志功能,因为当代码量较大时,就很难在代码中找到其对应的输出位置。