Java深入学习(4):Future模式

Future模式:

其实相当于是前端的Ajax

比如我们使用多线程下载文件时候,每一个线程都会发送HTTP请求资源。而我如何知道,文件下载完毕呢?

也就是说,主线程如何获得子线程的执行结果呢?

创建多线程中的实现runnable接口方式和继承thread类,然后start方法都是直接执行代码的,无法知道执行的结果(主线程无法知道进度)。

 

这里要说的是新方式:使用Callable接口和Future模式

public class CallableTest {
    public static void main(String[] args) throws Exception {
        ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
        Future<String> submit = newCachedThreadPool.submit(new TaskCallable());
        System.out.println("主线程运行");
        String result = submit.get();
        System.out.println(result);
    }
}

class TaskCallable implements Callable {
    @Override
    public String call() throws Exception {
        System.out.println("开始执行任务");
        Thread.sleep(3000);
        System.out.println("执行任务结束");
        return "success";
    }
}

打印:

主线程运行
开始执行任务
执行任务结束
success

 

Future模式核心:去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑

 

Future模式实例:对于多线程,如果线程A要等待线程B的结果,那么线程A没必要等待B,直到B有结果,可以先拿到一个未来的Future,等到B有结果时再取真实的结果

 

自己实现Future模式:

/**
 * 公共Data数据结果
 */
public abstract class Data {
    /**
     * 返回线程的执行结果
     * @return String
     */
    public abstract String getRequest();
}
/**
 * 获取真实数据
 */
public class RealData extends Data {

    private String result;

    RealData(String data) {
        System.out.println("正在使用data->" + data + " 进行网络请求");
        try {
            Thread.sleep(3000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("操作执行完毕");
        this.result = "success";
    }

    @Override
    public String getRequest() {
        return result;
    }
}
/**
 * 当有线程要获取RealData的时候
 * 程序会被阻塞
 * 等到RealData被注入才会使用getRequest方法
 */
public class FutureData extends Data {
    private boolean FLAG = false;
    private RealData realData;

    /**
     * 读取Data数据
     */
    public synchronized void setRealData(RealData realData) {
        //如果获取到数据直接返回
        if (FLAG) {
            return;
        }
        //如果没有获取到数据
        this.realData = realData;
        FLAG = true;
        notify();
    }

    @Override
    public synchronized String getRequest() {
        while (!FLAG) {
            try {
                wait();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return realData.getRequest();
    }
}
public class FutureClient {

    public Data submit(String requestData){
        FutureData futureData = new FutureData();
        new Thread(new Runnable() {
            @Override
            public void run() {
                RealData realData = new RealData(requestData);
                futureData.setRealData(realData);
            }
        }).start();
        return futureData;
    }
}

测试类:

public class Main {
    public static void main(String[] args) {
        FutureClient futureClient = new FutureClient();
        Data request = futureClient.submit("666");
        System.out.println("主线程数据发送成功");
        System.out.println("主线程执行其他任务");
        String result = request.getRequest();
        System.out.println(result);
    }
}

 

打印如下:

主线程数据发送成功
主线程执行其他任务
正在使用data->666 进行网络请求
操作执行完毕
success

 

    原文作者:一清
    原文地址: https://www.cnblogs.com/xuyiqing/p/11625130.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞