`

Future模式

阅读更多

http://www.cnblogs.com/edwardlost/archive/2010/12/26/1917238.html

 

Future模式

在多线程交互的中,经常有一个线程需要得到另个一线程的计算结果,我们常用的是Future异步模式来加以解决。

 

Future顾名思意,有点像期货市场的“期权”,是“对未来的一种凭证”,例如当我们买了某个房地产开发商的期房,交钱之后,开发商会给我们一个凭证(期权),这个凭证告诉我们等明年某个时候拿这个凭证就可以拿到我们所需要的房子,但是现在房子还没建好。市场上之所以有“期货”,也正由于有这种需求,才有这种供给。

 

这种应用在GUI上用的比较多,在设计模式中一般称为“虚拟代理模式”。

 

例如:现在有个这样的需求,Client向Server提交一个Request(int count,char c),希望获取一个由count个字符c构造出来的字符串。比如发送Request(10,'K'),那么反馈字符串“KKKKKKKKKK”,但是我们假设这个生成字符串的过程很费时间。

 

于是,为了获取比较好的交互性,我们的Server收到请求后,先构造一个FutureData,并把这个所谓的“期权(未来凭证)”反馈给Client;于此同时,通过另一个并发线程去构造一个真正的字符串RealData,并在构造完毕后,RealData给FutureData报告一个消息,说数据(期房)已经准备好了,此时Client可以通过期权拿到期房,但是假如我们的Client比较着急,还没等房子假好的时,就想要房子,怎么办呢?这个时候我们可以阻塞Client所在的线程,让Client等待,直到最后RealData通知FutureData说房子好了,才返回。

 

这里的要点:
(1)Server先给Client一个“期权”,同时开一个线程去干活建房子(未来的“现房”);
(2)当“现房”RealData准备好了的时候,如何告诉FutureData说已经准备好了。(本处采用“回调过程”借用观察者模式,来实现回调)
(3)如果客户比较着急,现房还没准备好的时候,就要取房,怎么办?  本处采用“阻塞”。

 

Data(公共数据接口)

1
2
3
4
5
package com.umpay.future;
  
public interface Data {
    public abstract String getContent();
}

 

FutureData(期权)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package com.umpay.future.extend;
  
import java.util.Observable;
import java.util.Observer;
  
import com.umpay.future.Data;
  
public class FutureData2 implements Data,Observer {
  
    /** 
     * 存放真实数据,并且标志真正的数据是否已经准备完毕
     * 被多线程享受
     * 如果realData2==null,表示数据还准备好
     * */
    private volatile RealData2 realData2 = null;
    /**
     * 查看真正的数据是否准备完毕
     * */
    public boolean isFinished() {
        return realData2 != null;
    }
      
    /**
     * 如果数据已经准备好,则返回真正的数据;
     * 否则,阻塞调用线程,直到数据准备完毕后,才返回真实数据;
     * */
    public String getContent() {
        synchronized (mutex) {
            while(!isFinished()) {//只要数据没有准备完毕,就阻塞调用线程
                try {
                    mutex.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return realData2.getContent();
        }
    }
  
    /**
     *  当 RealData2 准备完数据后,RealData2 应该通知 FutureData2 数据准备完毕。
     *  并在输入参数 realData 传入真实数据,在参数 event 传入事件(比如数据如期准备好了,或出了什么异常)
     *
     *  @param  realData    真实的数据
     *  @param  event       事件类型
     * */
    public void update(Observable realData, Object event) {
        System.out.println("通知...."+event);
        if(!(realData instanceof RealData2)) {
            throw new IllegalArgumentException("主题的数据类型必须是RealData2");
        }
        if(!(event instanceof String)) {
            throw new IllegalArgumentException("事件的数据类型必须是String");
        }
        synchronized (mutex) {
            if(isFinished()) {
                mutex.notifyAll();
                return;//如果数据已经准备好了,直接返回.
            }
            if("Finished".equals(event)) {
                realData2 = (RealData2)realData;//数据准备好了的时候,便可以通知数据准备好了
                mutex.notifyAll();//唤醒被阻塞的线程
            
        }
    }
  
    private Object mutex = new Object();
}

 

RealData(实际数据)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package com.umpay.future.extend;
  
import java.util.Observable;
  
import com.umpay.future.Data;
  
public class RealData2 extends Observable implements Data {
  
    private String content;
  
    public RealData2() {
          
    }
      
    public void createRealData2(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);
          
        //真实数据准备完毕了,通知FutureData2说数据已经准备好了.
        setChanged();//必须先设置本对象的状态发生了变化,并且通知所有的观察者
        notifyObservers("Finished");
    }
      
  
    public String getContent() {
        return content;
    }
}

 

服务端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package com.umpay.future.extend;
  
import com.umpay.future.Data;
  
public class HostServer2 {
  
    public Data request(final int count, final char c) {
        System.out.println("    request(" + count + ", " + c + ") BEGIN");
  
        // (1) 建立FutureData的实体
        final FutureData2 future2 = new FutureData2();
  
        // (2) 为了建立RealData的实体,启动新的线程
        new Thread() {
            public void run() {
                RealData2 realdata2 = new RealData2();
                realdata2.addObserver(future2);//以便当RealData2把数据准备完毕后,通过该回调口子,通知FutureData2表示数据已经贮备好了
                realdata2.createRealData2(count, c);
            }
        }.start();
  
        System.out.println("    request(" + count + ", " + c + ") END");
  
        // (3) 取回FutureData实体,作为传回值
        return future2;
    }
  
}

 

客户端代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.umpay.future;
  
import com.umpay.future.extend.HostServer2;
  
public class MainClient {
    public static void main(String[] args) {
//      testHostServer();
        testHostServer2();
    }
      
    static void testHostServer() {
        System.out.println("main BEGIN");
        HostServer hostServer = new HostServer();
        Data data1 = hostServer.request(10, 'A');
        Data data2 = hostServer.request(20, 'B');
        Data data3 = hostServer.request(30, 'C');
  
        System.out.println("main otherJob BEGIN");
//        try {
//            Thread.sleep(2000);
//        } catch (InterruptedException e) {
//        }
        System.out.println("main otherJob END");
  
        System.out.println("data1 = " + data1.getContent());
        System.out.println("data2 = " + data2.getContent());
        System.out.println("data3 = " + data3.getContent());
        System.out.println("main END");
  
    }
  
    static void testHostServer2() {
        System.out.println("main BEGIN");
        HostServer2 hostServer2 = new HostServer2();
        Data data1 = hostServer2.request(10, 'A');
        Data data2 = hostServer2.request(20, 'B');
        Data data3 = hostServer2.request(30, 'C');
  
        System.out.println("main otherJob BEGIN");
//        try {
//            Thread.sleep(2000);
//        } catch (InterruptedException e) {
//        }
        System.out.println("main otherJob 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. Future模式(异步调用)

2. Design Pattern: Future 模式

3. 什么是java future模式

 

分享到:
评论

相关推荐

    future模式案例代码

    Future模式核心思想是异步调用,这里具体实现代码,其思想是:网上订了一个货之后,他会立即返回下好订单给你,你可以去做其他事,不用再一直等这个货物到达,以后有时间,货物到了,你就可以拿这个订单,去取货。...

    老生常谈java中的Future模式

    下面小编就为大家带来一篇老生常谈java中的Future模式。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    31 凭票取餐—Future模式详解.pdf

    Java并发编程学习宝典(漫画版),Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习宝典(漫画版)Java并发编程学习...

    Spring Boot对Future模式的支持详解

    主要给大家介绍了关于Spring Boot对Future模式的支持的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用spring boot具有一定的参考学习价值,需要的朋友们下面来一起看看吧

    36种最新设计模式整理

    36种最新设计模式整理 Design Pattern: Simple Factory 模式 Design Pattern: Abstract Factory 模式 ...Future 模式 Read-Write-Lock 模式 Two-phase Termination 模式 Thread-Specific Storage 模式

    asyncj:使用 Future 模式或回调(NodeJS 风格)进行异步非阻塞编程的灵活而简单的库。 没有第三方依赖,没有重量级的包装器和类,没有废话,只需添加 maven 依赖并构建可扩展的应用程序

    灵活且超轻量级的库,用于使用 Future 模式、回调(NodeJS 风格)和异步非阻塞编程。 动机 该库的第一个目标是为 Java 8 提供模式的轻量级实现。此外,该库还提供对 Java 流水线的支持。 第二个目的是演示 Java 8 ...

    线程超时死掉

    Future接口是Java线程Future模式的实 现,可以来进行异步计算。 Future模式可以这样来描述:我有一个任务,提交给了Future,Future替我完成这个任务。期间我自己可以去做任何想做的事情。一段时 间之后,我就便...

    设计模式-.NET并行编程

    本书共7章:第1章主要介绍并行编程的基本概念与并行计算的基础理论,第2章主要介绍并行循环的知识,第3章介绍并行任务处理,第4章阐述并行合并计算的机理,第5章介绍future模式,第6章在前文的基础上深入探讨动态...

    设计模式NET并行编程高清完整版带书签

    本书共7章:第1章主要介绍并行编程的基本概念与并行计算的基础理论,第2章主要介绍并行循环的知识,第3章介绍并行任务处理,第4章阐述并行合并计算的机理,第5章介绍future模式,第6章在前文的基础上深入探讨动态...

    《美团大众点评微服务实践——服务框架-Pigeon-的设计与实现》.pdf

    Sync模式同步等待返回调用,Future模式可实现并行发出多个请求,Callback模式发出结果不等待返回,Oneway模式无需返回结果。 服务治理 Pigeon提供了服务治理机制,包括服务注册、服务发现、服务调用、服务降级等。...

    JAVA高质量并发详解,多线程并发深入讲解

    例如,通过讲解线程池、Future模式、Fork/Join框架等,帮助读者解决复杂的并发问题,提高系统的响应能力和吞吐量。此外,书中还深入剖析了并发编程中的常见问题,如死锁、活锁、饥饿等,并提供了相应的解决方案和...

    实战Java高并发程序设计(第2版)PPT模板.pptx

    5并行模式与算法 5.1探讨单例模式 5.3生产者-消费者模式 5.5future模式 5.2不变模式 5.4高性能的生产者-消费者模式:无锁的实现 5.6并行流水线 01 02 03 04 05 06 实战Java高并发程序设计(第2版)PPT模板全文共25...

    总结了Thread-Callable-Future的小demo

    自留demo,主要是Thread-Callable-Future的基本实现。 参考文章: 1、深入理解Callable ...2、彻底理解Java的Future模式: https://www.cnblogs.com/cz123/p/7693064.html

    java Future 接口使用方法详解

    主要介绍了java Future 接口使用方法详解,Future接口是Java线程Future模式的实现,可以来进行异步计算的相关资料,需要的朋友可以参考下

    简单讲解Java的Future编程模式

    主要介绍了Java的Future编程模式,包括对异步和并发的一些设计思维,需要的朋友可以参考下

    Augmented Analytics Is the Future of Data and Analytics

    1. 增强分析是使用机器学习进行自动数据准备、洞察发现和洞察分享的下一代数据分析模式,这种模式可以广泛服务于商业用户、机构工作者和全民数据科学家。 2. 增强分析能够让专业的数据客堂家专注于解决特定的问题和...

    java面试大全,从java基础到微服务,2月1号总结完毕版本

    java面试大全,从java基础到微服务,2月1号总结完毕版本,带有future模式实战以及forkjoin实战,另外带有搭建项目脚手架

    dubbo第三课作业1

    1、请把jdk里的future模式,使用步骤按自己的理解,描述一下2、请把dubbo消费端调用服务端过程中,几种角色:调用方、代理对象、协议对象、URL、目标服

    dubbo第四节1

    上堂课回顾1、异步调用 ---- future模式2、事件机制 --- 异步回调3、回声测试 --- 服务就绪清单4、泛化调用 -- 不通过接口类: 救急5、d

    Causal Recommendation:Progresses and Future Directions.pdf

    数据驱动的推荐系统在各种Web应用程序中表现出了巨大的成功,这归功于机器学习模型从大量的历史用户行为中识别模式(即相关性)的非凡能力。然而,这些模型仍然存在一些问题,如由于虚假相关性而产生的偏差和不公平。...

Global site tag (gtag.js) - Google Analytics