zoukankan      html  css  js  c++  java
  • 《图解Java多线程设计模式》之十:Future模式

    一,Future模式

    假设有一个方法需要花费很长的时间才能获取运行结果。那么,与其一直等待结果,不如先拿一张 提货单。获取提货单并不耗费时间。这里提货单就称为Future角色
    获取Future角色的线程会在稍后使用Future角色来获取运行结果
    在处理开始时先返回Future角色,等到其他线程出来终止后,在将结果设置到Future角色中。
    二,示例程序

    Data:访问数据的接口

    RealData:实际处理数据的类

    FutureData:表示RealData的提货单,

    Host:先拿提货单future实例,开启新线程创建RealData实例

    public interface Data {
    
        public abstract String 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){
    
                }
            }
            System.out.println("   making RealData("+count+" , "+ c +") end");
            this.content = new String(buffer);
        }
        @Override
        public String getContent() {
    
            return content;
        }
    
        @Override
        public String toString() {
            return "real.toString";
        }
    }
    public class FutureData implements Data {
        private RealData realData = null;
    
        private boolean ready = false;
    
        /**
         * 为Future类中的字段设置值
         * @param realData
         */
        public synchronized void setRealData(RealData realData) {
            if(ready){
                return;
            }
            this.realData = realData;
            this.ready = true;
            notifyAll();
        }
    
        /**
         * 还没有成功设置值之前 一直等待。设置成功后就返回值
         * @return
         */
        @Override
        public synchronized String getContent() {
            while (!ready){
                try {
                    wait();
                }catch (InterruptedException e){
    
                }
            }
            return realData.getContent();
        }
    
        @Override
        public String toString() {
            return "feature.toString";
        }
    }
    public class Host {
        public Data request(final int count, final char c){
            System.out.println("    request("+count+" , "+c+") begin");
            //1,创建FutureData实例
            final FutureData futureData = new FutureData();
            //2,启动一个新线程去创建RealData实例,耗时操作
            new Thread(){
                @Override
                public void run() {
                    RealData realData = new RealData(count,c);
                    futureData.setRealData(realData);
                }
            }.start();
            System.out.println("    request("+count+" , "+c+") end");
    
            //3,将Future实例作为返回值返回给调用者
            return futureData;
        }
    }
    public class Test {
        public static void main(String[] args) {
            System.out.println(" main begin ..........");
            Host host = new Host();
            Data data1 = host.request(10,'a');
            System.out.println("虚拟数据:data1 = "+data1.toString());
            Data data2 = host.request(20,'b');
            System.out.println("虚拟数据:data2 = "+data2.toString());
            Data data3 = host.request(30,'c');
            System.out.println("虚拟数据:data3 = "+data3.toString());
    
            System.out.println(" main OtherJobs begin");
            try {
                //模拟主线程处理其他业务
                Thread.sleep(2000);
            }catch (InterruptedException e){
    
            }
            System.out.println(" main OtherJobs end");
    
            System.out.println("真实数据:data1 = "+data1.getContent());
            System.out.println("真实数据:data2 = "+data2.getContent());
            System.out.println("真实数据:data3 = "+data3.getContent());
    
            System.out.println(" main end ..........");
        }
    }

    三,特点

    1,提高吞吐量
    首先这种模式可以提高程序响应性,但是耗时的操作花费的时间并没有减少啊,当程序在进行磁盘读写时,cpu处于等待状态,这时可以把cpu分配给其他的线程,就可以提高吞吐量了

    四,Callable和Future

    public class CallableAndFuture {
        public static void main(String[] args) {
    
            ExecutorService threadPool= Executors.newSingleThreadExecutor();
            /*
            threadPool.submit()  返回有结果的
             */
    
            Future<String> future=      //Future是用来接收submit的结果的。泛型和Callable的结果一样
            threadPool.submit(new Callable<String>() {//这里泛型了,
    
                @Override
                public String call() throws Exception {
                    Thread.sleep(1000);
                    System.out.println("处理结果中。。。。");
                    Thread.sleep(1000);
                    return "hello";
                }
            });
            System.out.println("等待结果");
            try {
                System.out.println("拿到结果"+future.get());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    
    }
    /**
     * 
     * CompletionService用于提交一组Callable任务,其task方法返回已完成的一个Callable任务对应的Future对象
     */
    public class CallableAndFuture2 {
        public static void main(String[] args) {
            ExecutorService threadPool2= Executors.newFixedThreadPool(10);
            CompletionService<Integer> completionService = new ExecutorCompletionService(threadPool2);
            for (int i = 0; i < 10; i++) {
                final int seq = i;
                completionService.submit(new Callable() {
                    @Override
                    public Integer call() throws Exception {
                        Thread.sleep(new Random().nextInt(5000));
                        return seq;
                    }
                });
            }
            while (true){
                try {
                    System.out.println(completionService.take().get());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } catch (ExecutionException e) {
                    e.printStackTrace();
                }
            }
        }
    }
  • 相关阅读:
    html头部属性全接触
    js中的window.onload和jquery中的load区别
    关机时,自动清除运行框的记录的设置方法
    MVC问题小总结,不断更新中...
    iis6 元数据库与iis6 配置的兼容 出错问题
    MVC对异步 Controller 的支持
    SQL Server2008安装报错,解决方案
    JavaScript有5个原始类型
    ASP.NET MVC中的拦截器
    F5负载均衡
  • 原文地址:https://www.cnblogs.com/inspred/p/9434558.html
Copyright © 2011-2022 走看看