zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    P2523 [HAOI2011]Problem c
    P2518 [HAOI2010]计数
    P2513 [HAOI2009]逆序对数列
    P2519 [HAOI2011]problem a
    P5020 货币系统
    P2580 于是他错误的点名开始了(Trie)
    P3805 【模板】manacher算法
    基础
    白兔的字符串(hash入门)
    ACM的分类训练题集(转载)
  • 原文地址:https://www.cnblogs.com/xuyiqing/p/11625130.html
Copyright © 2011-2022 走看看