学而时习之,不亦说乎!

                             --《论语》

什么是Future?

  考虑一个场景,为了完成某个业务,我需要同时查询三张表的三条独立数据。但是呢,这三张表数据量很大,三条数据分别需要消耗4s,6s,8s才能查询出来。在不考虑其他耗时的情况下,按顺序查出这三条数据,需要消耗18s时间。因为这三条数据其实是无上下文关系的,我们可以想到,如果我使用三个线程同时进行查询,那么会消耗多少时间呢?应该是耗时最长的那条数据所需的时间8s。那么,这儿分别实现这两种方式的查询。

项目整体结构如下:

entity包是通用实体类,normal包下是普通方式的查询代码,future包下是使用future模式查询代码。

1.创建一个普通的java项目。

2.创建一个通用实体类User:

package com.zby.entity;public class User {private String username;private String password;public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String toString() {return "User [username=" + username + ", password=" + password + "]";}}

3.使用普通方式按顺序查询的代码:

创建一个UserDao接口:

package com.zby.normal.dao;import com.zby.entity.User;public interface UserDao {User queryUserByUsername(String username);
}

创建UserDao的实现类UserDaoImpl:

package com.zby.normal.dao.impl;import com.zby.entity.User;
import com.zby.normal.dao.UserDao;public class UserDaoImpl implements UserDao {@Overridepublic User queryUserByUsername(String username) {try {System.out.println("开始对参数【" + username + "】进行数据库查询.....");// 模拟数据库操作耗时int sleepTime = username.length() * 1000;Thread.sleep(sleepTime);// 模拟数据库返回数据User user = new User();user.setUsername(username);user.setPassword("123456");System.out.println("完成对参数【" + username + "】进行数据库查询.....耗时" + sleepTime + "毫秒");return user;} catch (InterruptedException e) {e.printStackTrace();}return null;}}

测试类:

package com.zby.normal;import com.zby.entity.User;
import com.zby.normal.dao.UserDao;
import com.zby.normal.dao.impl.UserDaoImpl;public class GeneralApplication {public static void main(String[] args) {long startTime = System.currentTimeMillis();UserDao queryDao = new UserDaoImpl();User lisi = queryDao.queryUserByUsername("lisi");User wangwu = queryDao.queryUserByUsername("wangwu");User zhangsan = queryDao.queryUserByUsername("zhangsan");System.out.println("lisi:" + lisi);System.out.println("wangwu:" + wangwu);System.out.println("zhangsan:" + zhangsan);System.out.println("操作总耗时" + (System.currentTimeMillis() - startTime) + "毫秒");}}

控制台输出:

开始对参数【lisi】进行数据库查询.....
完成对参数【lisi】进行数据库查询.....耗时4000毫秒
开始对参数【wangwu】进行数据库查询.....
完成对参数【wangwu】进行数据库查询.....耗时6000毫秒
开始对参数【zhangsan】进行数据库查询.....
完成对参数【zhangsan】进行数据库查询.....耗时8000毫秒
lisi:User [username=lisi, password=123456]
wangwu:User [username=wangwu, password=123456]
zhangsan:User [username=zhangsan, password=123456]
操作总耗时18001毫秒

这个就很简单了,就是一般的数据库操作。要使用并发查询,需要考虑什么呢?

  首先,dao是要改的,我们不能在查询时直接返回实体类对象,因为我们的查询不是实时的,没法直接获取到结果。那我们这儿就考虑使用一个类,封装返回的数据,提供一个get方法,在需要的时候才获取需要的结果数据;提供一个set方法,使用另外的线程去查询结果,查询完毕后使用set到里面去,这样get的时候就有数据了。但是,如果我在使用get的时候数据还没有获取完成,这时怎么办?这儿就需要使用线程的阻塞唤醒机制:当结果还在获取中调用了get方法,会阻塞当前线程,等待获取完成后唤醒get。

4.使用Future模式的查询代码:

封装数据的FutureData类:

package com.zby.future.data;public class FutureData<T> {private T data;public synchronized void setData(T data) {this.data = data;notify();}public synchronized T getData() {while (null == data) {try {wait();} catch (InterruptedException e) {e.printStackTrace();}}return this.data;}}

改造后的UserDao接口:

package com.zby.future.dao;import com.zby.entity.User;
import com.zby.future.data.FutureData;public interface UserDao {FutureData<User> queryUserByUsername(String username);
}

改造后的UserDao接口实现类UserDaoImpl:

package com.zby.future.dao.impl;import com.zby.entity.User;
import com.zby.future.dao.UserDao;
import com.zby.future.data.FutureData;/*** * @描述:* @作者: zby* @创建时间: 2017年9月13日*/
public class QueryDaoImpl implements UserDao {@Overridepublic FutureData<User> queryUserByUsername(final String username) {final FutureData<User> data = new FutureData<User>();new Thread(new Runnable() {@Overridepublic void run() {try {System.out.println("开始对参数【" + username + "】进行数据库查询.....");// 模拟数据库操作耗时int sleepTime = username.length() * 1000;Thread.sleep(sleepTime);// 模拟数据库返回数据User user = new User();user.setUsername(username);user.setPassword("123456");System.out.println("完成对参数【" + username + "】进行数据库查询.....耗时" + sleepTime + "毫秒");data.setData(user);} catch (InterruptedException e) {e.printStackTrace();}}}).start();return data;}
}

测试类:

package com.zby.future;import com.zby.entity.User;
import com.zby.future.dao.UserDao;
import com.zby.future.dao.impl.QueryDaoImpl;
import com.zby.future.data.FutureData;public class FutureApplication {public static void main(String[] args) {long startTime = System.currentTimeMillis();UserDao queryDao = new QueryDaoImpl();FutureData<User> lisi = queryDao.queryUserByUsername("lisi");FutureData<User> wangwu = queryDao.queryUserByUsername("wangwu");FutureData<User> zhangsan = queryDao.queryUserByUsername("zhangsan");System.out.println("lisi:" + lisi.getData());System.out.println("wangwu:" + wangwu.getData());System.out.println("zhangsan:" + zhangsan.getData());System.out.println("耗时" + (System.currentTimeMillis() - startTime));}}

控制台输出:

开始对参数【lisi】进行数据库查询.....
开始对参数【wangwu】进行数据库查询.....
开始对参数【zhangsan】进行数据库查询.....
完成对参数【lisi】进行数据库查询.....耗时4000毫秒
lisi:User [username=lisi, password=123456]
完成对参数【wangwu】进行数据库查询.....耗时6000毫秒
wangwu:User [username=wangwu, password=123456]
完成对参数【zhangsan】进行数据库查询.....耗时8000毫秒
zhangsan:User [username=zhangsan, password=123456]
耗时8002

可以看到,这儿查询是并发开始的,查询时间得到了极大的提升,瓶颈仅仅是最耗时的那个查询。代码很简单,但是需要理解。

  在Java中也有一系列的例如java.util.concurrent.Future<V>,java.util.concurrent.Callable<V>,java.util.concurrent.Executors等一系列可以实现Future模式的类和接口,但是那些都是用起来简单,实现很复杂,重在理解。

转载于:https://www.cnblogs.com/zby9527/p/7519349.html

我理解的Future模式相关推荐

  1. Future模式介绍

    普通模式与Future模式的简单对比: 1. 普通模式在处理多任务时是串行的,在遇到耗时操作的时候只能等待,直到阻塞被解除,才会继续执行下一个任务 2. Future模式,只是发起了耗时操作,函数立马 ...

  2. 从理解Future模式到仿写JUC的Future模式

    1.Future模式 过生日,在线上定蛋糕的例子可以形象的解释Future模式. 两个步骤: 1.下单 - 委托制作蛋糕:你在线定下单订蛋糕,将制作蛋糕的工作委托给了蛋糕店. 2.取蛋糕:凭着在线支付 ...

  3. 彻底理解Java的Future模式

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_34173549/article/details/81074477 先上一个场景:假如你突然想做 ...

  4. Java Future接口、Future模式理解

    原文地址:https://blog.csdn.net/devinteng/article/details/23455733 Future接口介绍: 在Java中,如果需要设定代码执行的最长时间,即超时 ...

  5. 【小家java】一个例子让就能你彻底理解Java的Future模式,Future类的设计思想

    相关阅读 [小家java]java5新特性(简述十大新特性) 重要一跃 [小家java]java6新特性(简述十大新特性) 鸡肋升级 [小家java]java7新特性(简述八大新特性) 不温不火 [小 ...

  6. Java是如何实现Future模式的?万字详解!

    1 Future是什么? 先举个例子,我们平时网购买东西,下单后会生成一个订单号,然后商家会根据这个订单号发货,发货后又有一个快递单号,然后快递公司就会根据这个快递单号将网购东西快递给我们.在这一过程 ...

  7. java 回调模式_总结!!!总结!!!java回调以及future模式

    总是忘记,我这里直接写实际的东西,看其他的博客都是类图,文字描述,这里直接用代码描述. 疑问:什么是回调 回调,回调.要先有调用,才有调用者和被调用者之间的回调.所以在百度百科中是这样的: 软件模块之 ...

  8. 多线程设计模式(二):Future模式

    一.什么是Future模型: 该模型是将异步请求和代理模式联合的模型产物.类似商品订单模型.见下图: 客户端发送一个长时间的请求,服务端不需等待该数据处理完成便立即返回一个伪造的代理数据(相当于商品订 ...

  9. Future 模式详解(并发使用)

    我觉得很多讲Future模式的文章并没有深刻理解Future模式,其实Future模式只是生产者-消费者模型的扩展.经典"生产者-消费者"模型中消息的生产者不关心消费者何时处理完该 ...

最新文章

  1. 【读书笔记】iOS-网络-解析响应负载
  2. Ant Design 入门-参照官方文档使用组件
  3. python【数据结构与算法】并查集引入
  4. c#3.0系列:Object Initializer 和 Collection Initializer
  5. 我等这个含蓄的技术男当上了CEO
  6. android从一个活动到另一个活动,Android应用程序在将一个活动打开到另一个活动时崩溃...
  7. dc游戏java_极限飞车-穿越峡谷(DC出品)
  8. 邱跃鹏:互联网下半场,腾讯云要做信息能源发动机
  9. 计网笔记-计网总结-计网复习提纲-第一章.概述
  10. kafka第二次课!!!
  11. 熵值法 java_Java实现熵值法确定权重
  12. 设计模式笔记--访问者模式
  13. c#精华网站收集(转摘自梅川酷子的博客)
  14. 上瘾,一步步让你PICK ME
  15. Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
  16. demon算法 matlab,Ncut图像分割算法MATLAB实现
  17. tomcat资源请求慢_tomcat响应过慢——解决办法
  18. iPhone12蜜汁操作,环保还是揽财?
  19. UML的概念和模型之UML九种图
  20. 漏电继电器JOLX-GS62零序孔径Φ100

热门文章

  1. C#中的复制在unity中使用
  2. LFS安装过程记录(1)-准备工作
  3. BeginPaint和GetDC有什么区别?【转】
  4. 去掉IE的图片工具条
  5. impala的工作原理的详解(图文)
  6. Error configuring application listener of class org.springframework.web.context.ContextLoaderListene
  7. 接口测试--apipost解决传递json参数时字符串包含有@和/的问题
  8. 浅谈如何进行测试用例管理
  9. Jmeter 测试结果分析之聚合报告简介
  10. gstat | 空间插值(二)——克里金插值之普通克里金