• 《图解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();
                }
            }
        }
    }
  • 相关阅读:
    Java RunTime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. ......
    UVA 1597 Searching the Web
    UVA 1596 Bug Hunt
    UVA 230 Borrowers
    UVA 221 Urban Elevations
    UVA 814 The Letter Carrier's Rounds
    UVA 207 PGA Tour Prize Money
    UVA 1592 Database
    UVA 540 Team Queue
    UVA 12096 The SetStack Computer
  • 原文地址:https://www.cnblogs.com/inspred/p/9434558.html
Copyright © 2020-2023  润新知