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

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.}

时间: 2024-08-28 17:42:26

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

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

本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/51232004 前言 随着移动互联网的蓬勃发展,手机App层出不穷,其业务也随之变得错综复杂.针对于开发人员来说,可能之前的一个业务只需要调取一次第三方接口以获取数据,而如今随着需求的增加,该业务需调取多个不同的第三方接口.通常,我们处理方法是让代码同步顺序的去调取这些接口.显然,调取接口数量的增加必然会造成响应时间的增加,势必会对系统性能造成一定影响. 为

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

原文地址: http://blog.csdn.net/pistolove/article/details/51232004 Java Future ????通过Executors可以创建不同类似的线程池,常见的大概有下表几种类型,还有些可能为被列出.在实际应用中,个人感觉主要使用newCachedThreadPook和newFixedThreadPool来创建线程池. Executors创建线程池源码 //调用newCachedThreadPool方法,可以创建一个缓冲型线程池,而在改方法中通过

Java Future模式实现

Java Future模式简介 Future模式是Java多线程常用的模式,而且JDK也内置对Future模式的支持,比如在java.util.concurrent包下的FutureTask类.其核心思想在于:发出请求后,可以立即返回对象,但是这个对象实际上是个假对象,并不可立即使用,但是我们可以在干点别的事情后,就可以使用这个假对象获取结果了.这是为什么呢?因为在返回假对象的时候,偷偷的开启了一个线程去请求真正的结果数据.那么下面,我们来模拟实现下Future模式. 代码实现与分析 主流程是:

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

转自原文BeginInvoke 方法真的是新开一个线程进行异步调用吗? 参考以下代码: public delegate void treeinvoke(); private void UpdateTreeView() { MessageBox.Show(System.Threading.Thread.CurrentThread.Name); } private void button1_Click(object sender, System.EventArgs e) { System.Threa

java Future模式

Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Future模式,关于其他多线程设计模式的地址如下:关于其他多线程设计模式的地址如下:关于Master-Worker模式的详解: Java多线程编程中Master-Worker模式的详解关于Guarded Suspeionsion模式的详解: Java多线程编程中Guarded Suspeionsion模式

java Future模式核心思想(转)

Future模式的核心在于:去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑(根据<Java程序性能优化>). Future模式有点类似于商品订单.在网上购物时,提交订单后,在收货的这段时间里无需一直在家里等候,可以先干别的事情.类推到程序设计中时, 当提交请求时,期望得到答复时,如果这个答复可能很慢.传统的时一直等待到这个答复收到时再去做别的事情,但如果利用Future设计模式就无需等待答复 的到来,在等待答复的过程中可以干其他事情. 例如如下的请求调用过程时序图.

SpringBoot系列——@Async优雅的异步调用

前言 众所周知,java的代码是同步顺序执行,当我们需要执行异步操作时我们需要创建一个新线程去执行,以往我们是这样操作的: /** * 任务类 */ class Task implements Runnable { @Override public void run() { System.out.println(Thread.currentThread().getName() + ":异步任务"); } } //新建线程并执行任务类 new Thread(new Task()).sta

一位牛人的多线程和异步调用文章

转自小顾问原文 一位牛人的多线程和异步调用文章 首先申明:这篇文章不是我写的,我看到的一位牛人的,自己慢慢的消化了…… 摘要:本章讨论与智能客户端应用程序中多线程的使用有关的问题.为了最大限度地提高智能客户端应用程序的响应能力,需要仔细考虑如何和何时使用多线程.线程可以大大提高应用程序的可用性和性能,但是当您确定它们将如何与用户界面交互时,需要对其进行非常仔细的考虑. 线程是基本执行单元.单线程执行一系列应用程序指令,并且在应用程序中从头到尾都经由单一的逻辑路径.所有的应用程序都至少有一个线程,

C#同步和异步调用

这篇文章仅当总结之用,参考了很多前辈们的文章,加上了点点自己的理解 C#的同步和异步线程是依靠委托来完成,主要需要用到委托的Invoke方法,BeginInvoke和EndInvoke方法 所谓同步线就是阻塞当前线程来完成调用的方法,然后才继续调用当前线程的后面的操作,实际上都是在同一个线程中执行,效率不高.需要用到Invoke方法 异步线程不阻塞当前线程,而是把需要调用的方法加入线程池中,来同步执行,即同一时间两个及其以上的线程共同都在执行,效率很高.需要用到BeginInvoke和EndIn