Future模式理解及FutureTask应用场景

一、 Future模式理解

先说一下为什么要用future模式:两个任务没有必然的前后关系,如果在一个线程中串行执行,就有些浪费时间,不如让两个线程去并行执行这两个任务,执行完了到主线程去汇报就可以了。(让任务后台运行,不阻塞线程)

则使用Future模式耗费的时间为: max(TimeofTask1,TimeofTask2)。串行的话则是TimeofTask1+TimeofTask2。

接下来使用代码的类图:

先贴出源码,可以先看下源码理解一下,怎么使用就成了future模式。

Interface:

public interface Data {
    public String getResult();
}

RealData:

public class RealData implements Data{
    protected final String result;

    public RealData(String para) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 10; i++) {
            sb.append(para);
        }
        try {
            // 这里使用sleep,模拟很慢的构造RealData过程
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        result = sb.toString();
    }
}

FutureData

// FutureData是RealData的包装
public class FutureData implements Data {
    protected RealData realData = null;
    protected boolean isReady = false;
    public synchronized void setRealData(RealData realdata){
        if (isReady){
            return;
        }
        this.realData = realdata;
        isReady = true;
        // RealData注入完毕以后,通知getResult()
        notifyAll();
    }

    @Override
    public synchronized String getResult() {
        while (!isReady){
            try {
                // 等待RealData被注入,直到被notify
                wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return realData.result;
    }
}

首先我们要明确,RealData是我们真正需要的数据,FutureData只是做了一层封装,可以实现在得到RealData的过程中不阻塞当前线程。

我们重点来看FutureData,就两个方法,暂且把setRealData叫做注入数据方法,getResult是拿到最终数据方法。

一个状态位isReady,等待RealData注入完毕,就可以getResult了。没注入完毕,则阻塞当前线程。

有了这些信息,我们可以这样想,这个构建RealData很费时间,不如把这个构建任务扔到一个线程里去,当前线程去做其他事情。

使用方法:

public class FutureMainByMyself {
    public Data request(final String queryStr){
        // futureData包装了RealData
        final FutureData futureData = new FutureData();
        new Thread(){
            // RealData构建很慢,放在一个线程里慢慢去构建
            @Override
            public void run() {
                RealData realData = new RealData(queryStr);
                futureData.setRealData(realData);
            }
        }.start();
        return futureData;
    }

    public static void main(String[] args) {
        FutureMainByMyself client = new FutureMainByMyself();
        Data data = client.request("name");
        System.out.println("请求完毕");
        //这里才是真实的数据
        try {
            //这里的sleep代表了其他的业务逻辑,
            //在处理这些业务逻辑的同时,RealData被创建,从而充分利用了时间
            System.out.println(LocalTime.now());
            Thread.sleep(2000);
            System.out.println(LocalTime.now());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("数据=" +data.getResult() + " " + LocalTime.now());

    }
}

二、FutureTask应用场景和源码解析

FutureTask使用场景上面只是大致说了一下,下面我们来举一个具体的场景:API网关。

比方说用户打开一个订单页面:可能要查许多接口:订单信息,积分信息,退换货信息,这时候如果串行去查这么多东西,很费时间。

这些信息是没有必要的先后关系的,所以可以做出并行的。平时我们用软件也能注意到,先出来这块信息,再出来那块信息,这就是并行去查的结果,当然也可以等所有信息都拿到,再同时返回。

FutureTask源码解析:

原文地址:https://www.cnblogs.com/NoYone/p/8858051.html

时间: 2024-10-13 06:39:45

Future模式理解及FutureTask应用场景的相关文章

彻底理解Java的Future模式(转)

先上一个场景:假如你突然想做饭,但是没有厨具,也没有食材.网上购买厨具比较方便,食材去超市买更放心. 实现分析:在快递员送厨具的期间,我们肯定不会闲着,可以去超市买食材.所以,在主线程里面另起一个子线程去网购厨具. 但是,子线程执行的结果是要返回厨具的,而run方法是没有返回值的.所以,这才是难点,需要好好考虑一下. 模拟代码1: package test; public class CommonCook { public static void main(String[] args) thro

彻底理解Future模式

先上一个场景:假如你突然想做饭,但是没有厨具,也没有食材.网上购买厨具比较方便,食材去超市买更放心. 实现分析:在快递员送厨具的期间,我们肯定不会闲着,可以去超市买食材.所以,在主线程里面另起一个子线程去网购厨具. 但是,子线程执行的结果是要返回厨具的,而run方法是没有返回值的.所以,这才是难点,需要好好考虑一下. 模拟代码1: package test; public class CommonCook { public static void main(String[] args) thro

线程笔记:Future模式

线程技术可以让我们的程序同时做多件事情,线程的工作模式有很多,常见的一种模式就是处理网站的并发,今天我来说说线程另一种很常见的模式,这个模式和前端里的ajax类似:浏览器一个主线程执行javascript,页面渲染等操作,当我们使用ajax向服务端发起请求,由于这个过程很慢,ajax的异步模式可以让我们无需一直等待服务端的响应,而在这个等待结果时间里做其他的事情,这个模式在线程技术力称之为Future模式. Future模式和我前面文章里说到的html5技术里的worker技术差不多,当我们一个

线程技术 ? Future模式

线程技术可以让我们的程序同时做多件事情,线程的工作模式有很多,常见的一种模式就是处理网站的并发,今天我来说说线程另一种很常见的模式,这个模式和前端里的ajax类似:浏览器一个主线程执行javascript,页面渲染等操作,当我们使用ajax向服务端发起请求,由于这个过程很慢,ajax的异步模式可以让我们无需一直等待服务端的响应,而在这个等待结果时间里做其他的事情,这个模式在线程技术力称之为Future模式. Future模式和我前面文章里说到的html5技术里的worker技术差不多,当我们一个

同步调用,异步回调和 Future 模式

目标 通过与方法的同步调用,异步回调比较,理解 Future 模式 三者的不同 让我们先来明确一下同步与异步的不同.我们这里所说的同步和异步,仅局限在方法的同步调用和异步回调中.即,同步指的是调用一个方法,调用方要等待该方法所执行的任务完全执行完毕,然后控制权回到调用方:异步指的是调用一个方法,调用方不等该方法执行的任务完毕就返回,当任务执行完毕时会自动执行调用方传入的一块代码. 同步调用 void runTask { doTask1() doTask2() } 同步调用,执行完 doTask1

Java Thread系列(十)Future 模式

Java Thread系列(十)Future 模式 Future 模式适合在处理很耗时的业务逻辑时进行使用,可以有效的减少系统的响应时间,提高系统的吞吐量. 一.Future 模式核心思想 如下的请求调用过程时序图.当 call 请求发出时,需要很长的时间才能返回.左边的图需要一直等待,等返回数据后才能继续其他操作:而右边的 Future 模式的图中客户端则无需等到可以做其他的事情.服务器段接收到请求后立即返回结果给客户端,这个结果并不是真实的结果(是虚拟的结果),也就 是先获得一个假数据,然后

怎么用wait、notify巧妙的设计一个Future模式?

我们知道多线程可以实现同时执行多个任务(只是看起来是同时,其实是CPU的时间片切换特别快我们没感觉而已). 现在假设一个做饭的场景,你没有厨具也没有食材.你可以去网上买一个厨具,但是这段时间,你不需要闲着啊,可以同时去超市买食材. 设想这是两个线程,主线程去买食材,然后开启一个子线程去买厨具.但是,子线程是需要返回一个厨具的. 如果用普通的线程,只有一个Run方法,而Run方法是没有返回值的,这个时候该怎么办呢? 我们就可以用JDK提供的Future模式.在主线程买完食材之后,可以主动去获取子线

14.Java中的Future模式

jdk1.7.0_79  本文实际上是对上文<13.ThreadPoolExecutor线程池之submit方法>的一个延续或者一个补充.在上文中提到的submit方法里出现了FutureTask,这不得不停止脚步将方向转向Java的Future模式. Future是并发编程中的一种设计模式,对于多线程来说,线程A需要等待线程B的结果,它没必要一直等待B,可以先拿到一个未来的Future,等B有了结果后再取真实的结果. ExecutorService executor = Executors.

多线程设计模式 - Future模式之JAVA实现

在之前一篇博客中介绍了Future设计模式的设计思想以及具体实现,今天我们来讲一下使用JDK原生的包如何实现. JDK内置的Future主要使用到了Callable接口和FutureTask类. Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其他线程执行的任务.Callable接口的定义如下: public interface Callable<V> { /** * Computes a result, or throws an