我理解的Future模式
学而时习之,不亦说乎!
--《论语》
什么是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模式相关推荐
- Future模式介绍
普通模式与Future模式的简单对比: 1. 普通模式在处理多任务时是串行的,在遇到耗时操作的时候只能等待,直到阻塞被解除,才会继续执行下一个任务 2. Future模式,只是发起了耗时操作,函数立马 ...
- 从理解Future模式到仿写JUC的Future模式
1.Future模式 过生日,在线上定蛋糕的例子可以形象的解释Future模式. 两个步骤: 1.下单 - 委托制作蛋糕:你在线定下单订蛋糕,将制作蛋糕的工作委托给了蛋糕店. 2.取蛋糕:凭着在线支付 ...
- 彻底理解Java的Future模式
版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/qq_34173549/article/details/81074477 先上一个场景:假如你突然想做 ...
- Java Future接口、Future模式理解
原文地址:https://blog.csdn.net/devinteng/article/details/23455733 Future接口介绍: 在Java中,如果需要设定代码执行的最长时间,即超时 ...
- 【小家java】一个例子让就能你彻底理解Java的Future模式,Future类的设计思想
相关阅读 [小家java]java5新特性(简述十大新特性) 重要一跃 [小家java]java6新特性(简述十大新特性) 鸡肋升级 [小家java]java7新特性(简述八大新特性) 不温不火 [小 ...
- Java是如何实现Future模式的?万字详解!
1 Future是什么? 先举个例子,我们平时网购买东西,下单后会生成一个订单号,然后商家会根据这个订单号发货,发货后又有一个快递单号,然后快递公司就会根据这个快递单号将网购东西快递给我们.在这一过程 ...
- java 回调模式_总结!!!总结!!!java回调以及future模式
总是忘记,我这里直接写实际的东西,看其他的博客都是类图,文字描述,这里直接用代码描述. 疑问:什么是回调 回调,回调.要先有调用,才有调用者和被调用者之间的回调.所以在百度百科中是这样的: 软件模块之 ...
- 多线程设计模式(二):Future模式
一.什么是Future模型: 该模型是将异步请求和代理模式联合的模型产物.类似商品订单模型.见下图: 客户端发送一个长时间的请求,服务端不需等待该数据处理完成便立即返回一个伪造的代理数据(相当于商品订 ...
- Future 模式详解(并发使用)
我觉得很多讲Future模式的文章并没有深刻理解Future模式,其实Future模式只是生产者-消费者模型的扩展.经典"生产者-消费者"模型中消息的生产者不关心消费者何时处理完该 ...
最新文章
- 【读书笔记】iOS-网络-解析响应负载
- Ant Design 入门-参照官方文档使用组件
- python【数据结构与算法】并查集引入
- c#3.0系列:Object Initializer 和 Collection Initializer
- 我等这个含蓄的技术男当上了CEO
- android从一个活动到另一个活动,Android应用程序在将一个活动打开到另一个活动时崩溃...
- dc游戏java_极限飞车-穿越峡谷(DC出品)
- 邱跃鹏:互联网下半场,腾讯云要做信息能源发动机
- 计网笔记-计网总结-计网复习提纲-第一章.概述
- kafka第二次课!!!
- 熵值法 java_Java实现熵值法确定权重
- 设计模式笔记--访问者模式
- c#精华网站收集(转摘自梅川酷子的博客)
- 上瘾,一步步让你PICK ME
- Java 第十一届 蓝桥杯 省模拟赛 小明的城堡
- demon算法 matlab,Ncut图像分割算法MATLAB实现
- tomcat资源请求慢_tomcat响应过慢——解决办法
- iPhone12蜜汁操作,环保还是揽财?
- UML的概念和模型之UML九种图
- 漏电继电器JOLX-GS62零序孔径Φ100
热门文章
- C#中的复制在unity中使用
- LFS安装过程记录(1)-准备工作
- BeginPaint和GetDC有什么区别?【转】
- 去掉IE的图片工具条
- impala的工作原理的详解(图文)
- Error configuring application listener of class org.springframework.web.context.ContextLoaderListene
- 接口测试--apipost解决传递json参数时字符串包含有@和/的问题
- 浅谈如何进行测试用例管理
- Jmeter 测试结果分析之聚合报告简介
- gstat | 空间插值(二)——克里金插值之普通克里金