java future模式 所线程实现异步调用(转载)

在多线程交互的中2,经常有一个线程需要得到另个一线程的计算结果,我们常用的是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(公共数据接口)

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

FutureData(期权)

Java代码 
1.package com.umpay.future.extend;  
2. 
3.import java.util.Observable;  
4.import java.util.Observer;  
5. 
6.import com.umpay.future.Data;  
7. 
8.public class FutureData2 implements Data,Observer {  
9. 
10.     
15.    private volatile RealData2 realData2 = null;  
16.     
19.    public boolean isFinished() {  
20.        return realData2 != null;  
21.    }  
22.      
23.     
27.    public String getContent() {  
28.        synchronized (mutex) {  
29.            while(!isFinished()) {//只要数据没有准备完毕,就阻塞调用线程  
30.                try {  
31.                    mutex.wait();  
32.                } catch (InterruptedException e) {  
33.                    e.printStackTrace();  
34.                }  
35.            }  
36.            return realData2.getContent();  
37.        }  
38.    }  
39. 
40.     
47.    public void update(Observable realData, Object event) {  
48.        System.out.println("通知...."+event);  
49.        if(!(realData instanceof RealData2)) {  
50.            throw new IllegalArgumentException("主题的数据类型必须是RealData2");  
51.        }  
52.        if(!(event instanceof String)) {  
53.            throw new IllegalArgumentException("事件的数据类型必须是String");  
54.        }  
55.        synchronized (mutex) {  
56.            if(isFinished()) {  
57.                mutex.notifyAll();  
58.                return;//如果数据已经准备好了,直接返回.  
59.            }  
60.            if("Finished".equals(event)) {  
61.                realData2 = (RealData2)realData;//数据准备好了的时候,便可以通知数据准备好了  
62.                mutex.notifyAll();//唤醒被阻塞的线程  
63.            }   
64.        }  
65.    }  
66. 
67.    private Object mutex = new Object();  
68.} 
RealData(实际数据)

Java代码 
1.package com.umpay.future.extend;  
2. 
3.import java.util.Observable;  
4. 
5.import com.umpay.future.Data;  
6. 
7.public class RealData2 extends Observable implements Data {  
8. 
9.    private String content;  
10. 
11.    public RealData2() {  
12.          
13.    }  
14.      
15.    public void createRealData2(int count, char c) {  
16.        System.out.println("        making RealData(" + count + ", " + c  
17.                + ") BEGIN");  
18.        char[] buffer = new char[count];  
19.        for (int i = 0; i < count; i++) {  
20.            buffer[i] = c;  
21.            try {  
22.                Thread.sleep(100);  
23.            } catch (InterruptedException e) {  
24.            }  
25.        }  
26.        System.out.println("        making RealData(" + count + ", " + c  
27.                + ") END");  
28.        this.content = new String(buffer);  
29.          
30.        //真实数据准备完毕了,通知FutureData2说数据已经准备好了.  
31.        setChanged();//必须先设置本对象的状态发生了变化,并且通知所有的观察者  
32.        notifyObservers("Finished");  
33.    }  
34.      
35. 
36.    public String getContent() {  
37.        return content;  
38.    }  
39.}

服务端代码:

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

客户端代码:

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

java future模式 所线程实现异步调用(转载的更多相关文章

  1. 从Java future 到 Guava ListenableFuture实现异步调用

    从Java future 到 Guava ListenableFuture实现异步调用 置顶 2016年04月24日 09:11:14 皮斯特劳沃 阅读数:17570 标签: java异步调用线程非阻 ...

  2. 从Java Future到Guava ListenableFuture实现异步调用

    原文地址: http://blog.csdn.net/pistolove/article/details/51232004 Java Future     通过Executors可以创建不同类似的线程 ...

  3. BeginInvoke 方法真的是新开一个线程进行异步调用吗?

    转自原文BeginInvoke 方法真的是新开一个线程进行异步调用吗? BeginInvoke 方法真的是新开一个线程进行异步调用吗? 参考以下代码: public delegate void tre ...

  4. java Future 模式

    考慮這樣一個情況,使用者可能快速翻頁瀏覽文件中,而圖片檔案很大,如此在瀏覽到有圖片的頁數時,就會導致圖片的載入,因而造成使用者瀏覽文件時會有停頓 的現象,所以我們希望在文件開啟之後,仍有一個背景作業持 ...

  5. java Future模式

    Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...

  6. java Future模式的使用

    一.Future模式的使用. Future模式简述 传统单线程环境下,调用函数是同步的,必须等待程序返回结果后,才可进行其他处理. Futrue模式下,调用方式改为异步. Futrue模式的核心在于: ...

  7. Java并发编程:线程池的使用(转载)

    文章出处:http://www.cnblogs.com/dolphin0520/p/3932921.html Java并发编程:线程池的使用 在前面的文章中,我们使用线程的时候就去创建一个线程,这样实 ...

  8. Java 里如何实现线程间通信(转载)

    出处:http://www.importnew.com/26850.html 正常情况下,每个子线程完成各自的任务就可以结束了.不过有的时候,我们希望多个线程协同工作来完成某个任务,这时就涉及到了线程 ...

  9. C# 线程池异步调用

    许多应用程序使用多个线程,但这些线程经常在休眠状态中耗费大量的时间来等待事件发生.其他线程可能进入休眠状态,并且仅定期被唤醒以轮询更改或更新状态信息,然后再次进入休眠状态.为了简化对这些线程的管理,. ...

随机推荐

  1. POJ4852 Ants

    Ants Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 20047   Accepted: 8330 Description ...

  2. 洛谷P2912 [USACO08OCT]牧场散步Pasture Walking [2017年7月计划 树上问题 01]

    P2912 [USACO08OCT]牧场散步Pasture Walking 题目描述 The N cows (2 <= N <= 1,000) conveniently numbered ...

  3. 洛谷P1855 榨取kkksc03 [2017年4月计划 动态规划 09]

    P1855 榨取kkksc03 题目描述 洛谷的运营组决定,如果一名oier向他的教练推荐洛谷,并能够成功的使用(成功使用的定义是:该团队有20个或以上的成员,上传10道以上的私有题目,布置过一次作业 ...

  4. 怎么让一个不定宽高的div垂直水平居中?

    方法一:使用CSS3 transform 父盒子设置:position:relative; div设置:position:absolute;transform:translate(-50%,-50%) ...

  5. API安全验证之JWT(JSON WEB TOKEN) OLCMS

    假如www.olcms.com/getUserInfo获取用户信息,你怎么知道当前用户是谁?有人说登陆时候我把他UID写入session了,如果是API接口,没有session怎么办,那么就需要把UI ...

  6. 阿里云杨敬宇:5G时代,边缘计算将发挥更大价值

    “5G时代,边缘计算将发挥更大价值.”3月8日,阿里云边缘计算技术负责人杨敬宇向媒体表示,边缘计算作为5G时代的一项关键技术,未来将成为不可或缺的基础设施之一. 5G时代万物智联将真正成为现实,但对计 ...

  7. git 报错:没有权限 remote: error: unable to unlink old 'README.md' (Permission denied)

    解决:

  8. mytop安装,使用mytop监控MySQL性能 (总结)

    mytop 是一个类似 Linux 下的 top 命令风格的 MySQL 监控工具,可以监控当前的连接用户和正在执行的命令. 1. 安装TermReadKey    下载地址:  wget  http ...

  9. 基于遗传算法(Genetic Algorithm)的TSP问题求解(C)

    基于遗传算法的TSP问题求解(C) TSP问题: TSP(Travelling salesman problem): 译作“旅行商问题”, 一个商人由于业务的需要,要到n个城市,每个城市之间都有一条路 ...

  10. WPF:数据绑定总结(1) https://segmentfault.com/a/1190000012981745

    WPF:数据绑定总结(1) visual-studio c# 1.3k 次阅读  ·  读完需要 16 分钟 0 一.概念:什么是数据绑定? WPF中的数据绑定:是在应用程序 UI 与业务逻辑之间建立 ...