理解Future设计模式

1. 前言

在讲future模式之前,需要先理解什么是同步,什么是异步?

  • 同步:当任务a依赖于任务b的执行时,必须等待任务b执行完之后任务a才可以继续执行,此过程中任务a被阻塞,b也会被阻塞。可以类比我们打电话的场景(需要一直拿着电话)。
  • 异步:任务a调用任务b,任务a并不需要一直等到任务b执行完毕,任务b只是返回一个虚拟的结果给任务a,然后任务a可以继续做其他事情,等到任务b执行完成之后在通知任务a(回调),或者任务a主动去请求任务b要结果,可以类比发短信的场景,(发一条短信后,过了好一会再看下有没有回复)。

2. Future模式举列

    future模式就是异步的一种体现,举个例子,当我们发Ajax请求的时候,后台处理就属于异步的,它会先返回一个result给前端,同时进行后台数据处理等一系列操作,用户无需一直等待请求的结果,可以继续浏览或者操作其他内容。


image.png
package com.future;

public interface Data {
    String getRequest();
}
package com.future;

public class RealData implements Data{

    private String result ;
    
    public RealData (String queryStr){
        System.out.println("根据" + queryStr + "进行查询,这是一个很耗时的操作..");
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("操作完毕,获取结果");
        result = "查询结果";
    }
    
    public String getRequest() {
        return result;
    }

}
package com.future;

public class FutureData implements Data{
    /**
     * 这个是真实数据的代理对象
     * 和真实数据对象实现相同的接口,并且持有真实数据对象的引用
     */
    
    private RealData realData;
    
    private boolean isReady = false;
    
    public synchronized void setRealData(RealData realData){
        //如果已经装载完毕了,就直接返回 
        if(isReady){
            return;
        }
        //装载真实的对象
        this.realData = realData;
        isReady = true;
        //进行通知        
        notify();
    }
    
    public synchronized String getRequest() {
        //如果没装载好,程序就一直处于阻塞状态
        if(!isReady){
            try {
                wait();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block                
               e.printStackTrace();
            }
        }
        return this.realData.getRequest();
    }
}
package com.future;

public class FutureClient {
    
    public Data request(final String queryStr){
        // 客户端请求,这时候只需要创建一个包装对象先返回给客户端
        final FutureData futureData = new FutureData(); 
        // 启动一个新的线程,去加载真实的数据,传递给这个代理对象
        new Thread(
                new Runnable() {
                    public void run() {
                        //在这个线程里可以慢慢的加载真实对象,然后传递给代理对象
                        RealData realData = new RealData(queryStr);
                        futureData.setRealData(realData);
                    }
                }
                ).start();
        //先把new出来的对象返回去
        return futureData;
    }
    
    
    public static void main(String[] args) {
        
        FutureClient fc = new FutureClient();
        Data data = fc.request("请求参数");
        System.out.println("请求发送成功");
        System.out.println("做其他的事情...");
        
        String result = data.getRequest();
        System.out.println(result);
        
    }
}

     主线程调用request函数后不会阻塞,而是立即返回继续执行其他任务,再去查询之前request的结果。异步本质上还是开了多线程!!

Future是非常常用的多线程设计模式,在JDK中也内置了Future模式的实现。这些类在java.util.concurrent包里面,其中最为重要的是FutureTask类,后面文章会讲到FutureTask.

你可能感兴趣的:(理解Future设计模式)