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. Hackerrank--Divisibility of Power(Math)

    题目链接 You are given an array A of size N. You are asked to answer Q queries. Each query is of the for ...

  2. 建筑设计类软件整理ACDSee,PS,CAD,Ecotect,SketchUp,Phoenics,Revit,Rhino,

    关于建筑设计类软件整理 1 建筑设计类专业最常用软件如下,包括SU,CAD, REVIT,PS等. 2 sketch up 简称SU,中文名草图大师,在推敲方案,拉推体块时有着不可或缺的作用,而且随着 ...

  3. android 复制到剪切板

    The Clipboard Framework 当使用clipboard framework时,把数据放在一个剪切对象(clip object)里,然后这个对象会放在系统的剪贴板里. clip obj ...

  4. 链接的属性href=“?” ?该些什么及优缺点

    <a onclick="{jscode}">是很常见的一种js运用方式,使用时经常会加一个href=“###”即<a onclick="{jscode} ...

  5. java swing同时向jlabel添加图片和文字,并且设置文字的位置

    jLabColor.setVerticalTextPosition(JLabel.TOP);//靠上 jLabColor.setHorizontalTextPosition(JLabel.CENTER ...

  6. oracle-约束-序列

    概要图 一 约束 --问题:往表中插入数据的时候,可能出现一些问题,比如:重复插入数据,内容不对(性别) --如何保证数据库表中数据的完整性和一致性呢? 约束是强加在表上的规则或条件,确保数据库满足业 ...

  7. MyBatis中动态加载where条件

    1.trim 2.where 1 = 1 where 1=1 <if test="beginDate !=null and beginDate !='' "> and ...

  8. Leetcode48. Rotate Image旋转图像

    给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: 你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵.请不要使用另一个矩阵来旋转图像. 示例 1: 给定 m ...

  9. Axure之母版窗口

  10. Django用户登陆以及跳转后台管理页面2

    请先写好以下,再来替换文件 Django用户登陆以及跳转后台管理页面1http://www.cnblogs.com/ujq3/p/7891774.html from django.shortcuts ...