利用多线程实现Future模式

一、Futrue模式

客户端发送一个长时间的请求,服务端不需等待该数据处理完成便立即返回一个伪造的代理数据(相当于商品订单,不是商品本身),用户也无需等待,先去执行其他的若干操作后,再去调用服务器已经完成组装的真实数据。

该模型充分利用了等待的时间片段。简单来说就是,如果线程A要等待线程B的结果,那么线程A没必要等待B,直到B有结果,可以先拿到一个未来的Future,等B有结果是再取真实的结果。

在多线程中经常举的一个例子就是:网络图片的下载,刚开始是通过模糊的图片来代替最后的图片,等下载图片的线程下载完图片后在替换。而在这个过程中可以做一些其他的事情。

二、Future模式的代码实现

1、创建公共数据接口

 1 package com.ietree.basicskill.mutilthread.designpattern;
 2
 3 /**
 4  * Created by Root on 5/12/2017.
 5  */
 6 public interface Data {
 7
 8     String getRequest();
 9
10 }

2、创建FutureData对象,当有程序想要获取RealData的时候,程序会被阻塞,等到RealData被注入才会使用getReal()方法

 1 package com.ietree.basicskill.mutilthread.designpattern;
 2
 3 /**
 4  * Created by Root on 5/12/2017.
 5  */
 6 public class FutureData implements Data {
 7
 8     private RealData realData;
 9
10     private boolean isReady = false;
11
12     public synchronized void setRealData(RealData realData) {
13         // 如果已经装载完毕了,就直接返回
14         if (isReady) {
15             return;
16         }
17         // 如果没装载,进行装载真实对象
18         this.realData = realData;
19         isReady = true;
20         // 进行通知
21         notify();
22     }
23
24     @Override
25     public synchronized String getRequest() {
26         // 如果没装载好,程序就一直处于阻塞状态
27         while (!isReady) {
28             try {
29                 wait();
30             } catch (InterruptedException e) {
31                 e.printStackTrace();
32             }
33         }
34         // 装载好了直接获取数据即可
35         return this.realData.getRequest();
36     }
37 }

3、真实数据RealData类

 1 package com.ietree.basicskill.mutilthread.designpattern;
 2
 3 /**
 4  * Created by Root on 5/12/2017.
 5  */
 6 public class RealData implements Data {
 7
 8     private String result;
 9
10     public RealData(String queryStr) {
11         System.out.println("根据" + queryStr + "进行查询,这是一个很耗时间的操作......");
12         try {
13             Thread.sleep(5000);
14         } catch (InterruptedException e) {
15             e.printStackTrace();
16         }
17         System.out.println("操作完毕,获取结果");
18         result = "查询结果";
19     }
20
21     @Override
22     public String getRequest() {
23         return result;
24     }
25 }

4、客户端代理类

 1 package com.ietree.basicskill.mutilthread.designpattern;
 2
 3 /**
 4  * Created by Root on 5/12/2017.
 5  */
 6 public class FutureClient {
 7
 8     public Data request(final String queryStr) {
 9         //1 我想要一个代理对象(Data接口的实现类)先返回给发送请求的客户端,告诉他请求已经接收到,可以做其他的事情
10         final FutureData futureData = new FutureData();
11         //2 启动一个新的线程,去加载真实的数据,传递给这个代理对象
12         new Thread(new Runnable() {
13             @Override
14             public void run() {
15                 //3 这个新的线程可以去慢慢的加载真实对象,然后传递给代理对象
16                 RealData realData = new RealData(queryStr);
17                 futureData.setRealData(realData);
18             }
19         }).start();
20
21         return futureData;
22     }
23
24 }

5、测试调用

 1 package com.ietree.basicskill.mutilthread.designpattern;
 2
 3 /**
 4  * Created by Root on 5/12/2017.
 5  */
 6 public class FutureTest {
 7
 8     public static void main(String[] args) {
 9         FutureClient fc = new FutureClient();
10         Data data = fc.request("请求参数");
11         System.out.println("请求发送成功!");
12
13         try {
14             //处理其他业务
15             //这个过程中,真实数据RealData组装完成,重复利用等待时间
16             System.out.println("做其它的事情......");
17             Thread.sleep(2000);
18         } catch (InterruptedException e) {
19             e.printStackTrace();
20         }
21
22         // 获取真实数据
23         String result = data.getRequest();
24         System.out.println(result);
25     }
26
27 }

程序运行结果:

请求发送成功!
做其它的事情......
根据请求参数进行查询,这是一个很耗时间的操作......
操作完毕,获取结果
查询结果

第二种写法(没有实际运用过):

 1 package com.ietree.basicskill.mutilthread.designpattern;
 2
 3 import java.util.ArrayList;
 4 import java.util.List;
 5 import java.util.concurrent.Callable;
 6 import java.util.concurrent.ExecutionException;
 7 import java.util.concurrent.ExecutorService;
 8 import java.util.concurrent.Executors;
 9 import java.util.concurrent.Future;
10
11 /**
12  * Created by Root on 5/12/2017.
13  */
14 public class FutureTest2 {
15
16     private static class Task implements Callable<String> {
17         @Override
18         public String call() throws Exception {
19             // 模拟真实事务的处理过程,这个过程是非常耗时的。
20             Thread.sleep(5000);
21             return "call return ";
22         }
23     }
24
25     public static void main(String[] args) throws InterruptedException, ExecutionException {
26
27         List<Future<String>> futures = new ArrayList<Future<String>>();
28         ExecutorService executorService = Executors.newCachedThreadPool();
29
30         System.out.println("已经提交资源申请");
31         for (int i = 0; i < 10; i++) {
32             futures.add(executorService.submit(new Task()));
33         }
34
35         for (Future<String> future : futures) {
36             // 判断资源是不是已经准备完毕,准备完毕直接获取。
37             if (!future.isDone()) {
38                 System.out.println("资源还没有准备好");
39             }
40             System.out.println(future.get());
41         }
42         executorService.shutdown();
43     }
44 }
时间: 2024-10-03 10:57:12

利用多线程实现Future模式的相关文章

多线程设计模式 - Future模式

Future模式是多线程开发中非常常见的一种设计模式,它的核心思想是异步调用.这类似我们日常生活中的在线购物流程,带在购物网看着一件商品时可以提交表单,当订单完成后就可以在家里等待商品送货上门.或者说更形象的是我们发送Ajax请求的时候,页面是异步的进行后台处理,用户无需等待请求的结果,可以继续浏览或操作其他内容. 如上图所示,客户端调用购物请求,服务端程序不等数据处理完成便立即返回客户端一个伪造的数据,(相当于订单,而不是真实的商品)这时候由服务端自己偷偷摸摸的发送了一个other call(

多线程设计模式 - Future模式之JAVA实现

在之前一篇博客中介绍了Future设计模式的设计思想以及具体实现,今天我们来讲一下使用JDK原生的包如何实现. JDK内置的Future主要使用到了Callable接口和FutureTask类. Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其他线程执行的任务.Callable接口的定义如下: public interface Callable<V> { /** * Computes a result, or throws an

转多线程设计模式 - Future模式之JAVA原生实现

在之前一篇博客中介绍了Future设计模式的设计思想以及具体实现,今天我们来讲一下使用JDK原生的包如何实现. JDK内置的Future主要使用到了Callable接口和FutureTask类. Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其他线程执行的任务.Callable接口的定义如下: public interface Callable<V> { /** * Computes a result, or throws an

Java多线程编程中Future模式的详解&lt;转&gt;

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

Java多线程Future模式

Java多线程Future模式有些类似于Ajax的异步请求Future模式的核心在于:去除了主函数的等待时间,并使得原本需要等待的时间段可以用于处理其他业务逻辑 假设服务器的处理某个业务,该业务可以分成AB两个过程,并且AB两个过程之间不需要彼此的返回结果 A过程需要1秒钟,B过程需要2秒钟,主线程其他操作2秒钟按照正常编写,程序大概需要执行5秒如果按照Future模式只需要执行2秒(取其中运行时间最久的线程的运行时间) Future模式的核心实现在于两个方面 1.多线程运行 主线程采用多线的方

多线程(10) — Future模式

Future模式是多线程开发中常用常见的一种设计模式,它的核心思想是异步调用.在调用一个函数方法时候,如果函数执行很慢,我们就要进行等待,但这时我们可能不着急要结果,因此我们可以让被调者立即返回,让它在后台慢慢处理这个请求,对于调用者来说可以先处理一些其他事物,在真正需要数据的场合再去尝试获得需要的数据.对于Future模式来说,虽然它无法立即给出你需要的数据,但是它们返回一个契约给你,将来你可以凭借这个契约去重新获取你需要的信息.主要的角色有: Main:系统启动,调用Client发出请求.

Java之多线程中的Future模式

应用场景:线程A需要线程B的执行结果,但没必要一直等待线程B执行完,这个时候可以先拿到未来的Future对象,等线程B执行完再来取真实结果. 定义RealData真实数据类,其构造函数很慢,是用户最后需要使用的数据, static class RealData<T> { protected T result; public RealData(T result) { this.result = result; } public T getResult() { return result; } }

多线程手写Future模式

future模式 在进行耗时操作的时候,线程直接阻塞,我们需要优化这样的代码,让他再启动一个线程,不阻塞.可以执行下面的代码. 这个时候我们就用到了未来者模式 future设计类 只有一个方法 public interface Future<T> { T get() throws InterruptedException; } futureTask 类 public interface FutureTask<T> { T call(); } asyncFuture 类是fufure

多线程异步调用之Future模式

一.什么是异步调用 当我们调用一个函数的时候,如果这个函数的执行过程是很耗时的,我们就必须要等待,但是我们有时候并不急着要这个函数返回的结果.因此,我们可以让被调者立即返回,让他在后台慢慢的处理这个请求.对于调用者来说,则可以先处理一些其他事情,在真正需要数据的时候再去尝试获得需要的数据(这个真正需要数据的位置也就是上文提到的阻塞点).这也是Future模式的核心思想:异步调用. 到了这里,你可能会想CountDownLatch不是也可以实现类似的功能的吗?也是可以让耗时的任务通过子线程的方式去