实现Futrue接口

  1. public class MsgFuture<V> implements java.util.concurrent.Future<V> {
  2. ...
  3. ...
  4. }

  

Future的主要特性为Future.get()、

  1. get()
  1. get(long timeout, TimeUnit unit)

    主要思路如下:
    构造MsgFuture时,设置开始时间,这里是sendTime;设置timeout,默认get()方法的超时时间,我们的程序不可能会无限等待
    默认的get()对应的值域是result,默认为一个NULL对象,标识没有返回数据

    result的值需要其他线程在做完任务后将值写到Future对象中,这里暴露了一个方法setResult(object)
  1. /**
  2. * 设置结果值result,唤醒condition {@link #get(long, TimeUnit)}
  3. * @param result
  4. */
  5. public synchronized void setResult(Object result) {
  6. reentrantLock.lock();
  7. try {
  8. this.result = result;
  9. condition.signalAll();
  10. }finally {
  11. reentrantLock.unlock();
  12. }
  13.  
  14. }

  使用ReentrantLock来进行数据可见性控制

condition.signalAll()可以唤醒condition.await的阻塞wait

至于其他线程如何调用到setResult(object)方法,可以使用ConcurrentHashMap,key为msgId,值为MsgFuture对象,设置成一个全局的,或两个线程都可访问,其他线程根据msgId获取到MsgFuture,然后调用setResult(object)方法

  1. /**
  2. * 获取结果,如果到达timeout还未得到结果,则会抛出TimeoutException
  3. * @param timeout
  4. * @param unit
  5. * @return
  6. * @throws InterruptedException
  7. * @throws TimeoutException
  8. */
  9. @SuppressWarnings("all")
  10. public V get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
  11. long left = getLeftTime(timeout, unit); //根据timeout配置获取剩余的世界
  12. if(left < 0){
  13. //已经没有剩余时间
  14. if(isDone()){ //如果已经完成,直接放回结果
  15. return (V)this.result;
  16. }else{
  17. //timeout
  18. throw new TimeoutException("返回超时,后续的响应将会被丢弃abort");
  19. }
  20. }else{
  21.  
  22. reentrantLock.lock(); //同步
  23. try {
  24. //获取锁后先判断是否已经完成,防止无意义的await
  25. if(isDone()){ //先判断是否已经完成
  26. return (V)this.result; //直接返回
  27. }
  28. logger.debug("await "+left+" ms");
  29. condition.await(getLeftTime(timeout, unit), TimeUnit.MILLISECONDS); //没有返回,阻塞等待,如果condition被唤醒,也会提前退出
  30. }finally {
  31. reentrantLock.unlock();
  32. }
  33. if(isDone()){ //被唤醒或超时时间已到,尝试判断是否完成
  34. return (V)this.result; //返回
  35. }
  36.  
  37. throw new TimeoutException("未获取到结果"); //超时
  38. }
  39. }

  

  1. public boolean isDone() {
  2. return this.result != NULL;
  3. }

  



  1. 全部代码
  1. public class MsgFuture<V> implements java.util.concurrent.Future<V> {
  2.  
  3. private final static Logger logger = LoggerFactory.getLogger(MsgFuture.class);
  4.  
  5. /**
  6. * 全局的空对象,如果Future获取到值了,那么一定不是NULL
  7. */
  8. private final static Object NULL = new Object();
  9. /**
  10. * 主锁
  11. */
  12. private final ReentrantLock reentrantLock = new ReentrantLock();
  13.  
  14. /**
  15. * 条件,利用它的condition.await(left, TimeUnit.MILLISECONDS)和notifyAll方法来实现阻塞、唤醒
  16. */
  17. private final Condition condition = reentrantLock.newCondition();
  18.  
  19. private int timeout;
  20.  
  21. private volatile Object result = NULL;
  22.  
  23. private long sendTime;
  24.  
  25. public MsgFuture(int timeout, long sendTime) {
  26. this.timeout = timeout;
  27. this.sendTime = sendTime;
  28. }
  29.  
  30. public boolean cancel(boolean mayInterruptIfRunning) {
  31. return false;
  32. }
  33.  
  34. public boolean isCancelled() {
  35. return false;
  36. }
  37.  
  38. public boolean isDone() {
  39. return this.result != NULL;
  40. }
  41.  
  42. /**
  43. * 获取future结果
  44. * @return
  45. * @throws InterruptedException
  46. */
  47. public V get() throws InterruptedException {
  48. logger.debug("sendTime:{}",sendTime);
  49. try {
  50. return get(timeout, TimeUnit.MILLISECONDS);
  51. } catch (TimeoutException e) {
  52. logger.error("获取future结果异常", e);
  53. }
  54. return null;
  55. }
  56.  
  57. /**
  58. * 获取结果,如果到达timeout还未得到结果,则会抛出TimeoutException
  59. * @param timeout
  60. * @param unit
  61. * @return
  62. * @throws InterruptedException
  63. * @throws TimeoutException
  64. */
  65. @SuppressWarnings("all")
  66. public V get(long timeout, TimeUnit unit) throws InterruptedException, TimeoutException {
  67. long left = getLeftTime(timeout, unit);
  68. if(left < 0){
  69. //已经没有剩余时间
  70. if(isDone()){
  71. return (V)this.result;
  72. }else{
  73. //timeout
  74. throw new TimeoutException("返回超时,后续的响应将会被丢弃abort");
  75. }
  76. }else{
  77.  
  78. reentrantLock.lock();
  79. try {
  80. //获取锁后先判断是否已经完成,防止无意义的await
  81. if(isDone()){
  82. return (V)this.result;
  83. }
  84. logger.debug("await "+left+" ms");
  85. condition.await(getLeftTime(timeout, unit), TimeUnit.MILLISECONDS);
  86. }finally {
  87. reentrantLock.unlock();
  88. }
  89. if(isDone()){
  90. return (V)this.result;
  91. }
  92.  
  93. throw new TimeoutException("未获取到结果");
  94. }
  95. }
  96.  
  97. /**
  98. * 设置结果值result,唤醒condition {@link #get(long, TimeUnit)}
  99. * @param result
  100. */
  101. public synchronized void setResult(Object result) {
  102. reentrantLock.lock();
  103. try {
  104. this.result = result;
  105. condition.signalAll();
  106. }finally {
  107. reentrantLock.unlock();
  108. }
  109.  
  110. }
  111.  
  112. /**
  113. * 计算剩余时间
  114. * @param timeout
  115. * @param unit
  116. * @return
  117. */
  118. private long getLeftTime(long timeout, TimeUnit unit){
  119. long now = System.currentTimeMillis();
  120. timeout = unit.toMillis(timeout); // 转为毫秒
  121. return timeout - (now - sendTime);
  122. }
  123.  
  124. /*public static void main(String[] args) {
  125. MsgFuture msgFuture = new MsgFuture(2000,System.currentTimeMillis());
  126.  
  127. //测试先唤醒、后get是否正常
  128. msgFuture.setResult("yoxi");
  129.  
  130. try {
  131. System.out.println(msgFuture.get(2000,TimeUnit.MILLISECONDS));
  132. } catch (InterruptedException e) {
  133. logger.error("Interrupt异常", e);
  134. } catch (TimeoutException e) {
  135. logger.error("测试先唤醒,后get出错", e);
  136. }
  137. }*/
  138. }

  



java如何实现一个Future的更多相关文章

  1. java多线程之Future和FutureTask

    Executor框架使用Runnable 作为其基本的任务表示形式.Runnable是一种有局限性的抽象,然后可以写入日志,或者共享的数据结构,但是他不能返回一个值. 许多任务实际上都是存在延迟计算的 ...

  2. Java多线程编程中Future模式的详解

    Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...

  3. Java多线程编程中Future模式的详解<转>

    Java多线程编程中,常用的多线程设计模式包括:Future模式.Master-Worker模式.Guarded Suspeionsion模式.不变模式和生产者-消费者模式等.这篇文章主要讲述Futu ...

  4. Java 并发编程——Callable+Future+FutureTask

    Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...

  5. 使用executor、callable以及一个Future 计算欧拉数e

    package test; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMo ...

  6. 用Java语言编写一个简易画板

    讲了三篇概博客的概念,今天,我们来一点实际的东西.我们来探讨一下如何用Java语言,编写一块简易的画图板. 一.需求分析 无论我们使用什么语言,去编写一个什么样的项目,我们的第一步,总是去分析这个项目 ...

  7. 如何在JAVA中实现一个固定最大size的hashMap

    如何在JAVA中实现一个固定最大size的hashMap 利用LinkedHashMap的removeEldestEntry方法,重载此方法使得这个map可以增长到最大size,之后每插入一条新的记录 ...

  8. 利用java实现的一个发送手机短信的小例子

    今天闲来无事,在微博上看到一个关于用java实现的一个发送手机短信的程序,看了看,写的不太相信,闲的没事,把他整理下来,以后可能用得着 JAVA发送手机短信,流传有几种方法:(1)使用webservi ...

  9. 教你如何使用Java手写一个基于链表的队列

    在上一篇博客[教你如何使用Java手写一个基于数组的队列]中已经介绍了队列,以及Java语言中对队列的实现,对队列不是很了解的可以我上一篇文章.那么,现在就直接进入主题吧. 这篇博客主要讲解的是如何使 ...

随机推荐

  1. java安全编码指南之:输入校验

    目录 简介 在字符串标准化之后进行校验 注意不可信字符串的格式化 小心使用Runtime.exec() 正则表达式的匹配 简介 为了保证java程序的安全,任何外部用户的输入我们都认为是可能有恶意攻击 ...

  2. 4.案例 - NIO实现TCP通信

    服务端: package cn.tedu.nio.channel; import java.net.InetSocketAddress; import java.nio.ByteBuffer; imp ...

  3. 有向图的基本算法-Java实现

    有向图 有向图同无向图的区别为每条边带有方向,表明从一个顶点至另一个顶点可达.有向图的算法多依赖深度搜索算法. 本文主要介绍有向图的基本算法,涉及图的表示.可达性.检测环.图的遍历.拓扑排序以及强连通 ...

  4. 【Unity 插件】Lean Pool 使用

    2020-09-11 Lean Pool 是一个轻量级的游戏对象池库,它可以轻松的帮助你的游戏提高性能.当然,Lean Pool也可以工作于普通的C#类. 目录: 1.Lean Pool使用 2.Le ...

  5. kali上密码工具使用例如mudusa,hydra等

    思路 各种密码类别大致数学原理 https://blog.csdn.net/carol980206/article/details/96705859 https://www.jianshu.com/p ...

  6. mysql-18-function

    #函数 /* 存储过程:可以有0个或多个返回,适合批量插入.批量更新 函数:有且仅有一个返回,适合处理数据后返回一个结果 */ #一.创建语法 /* create function 函数名(参数列表) ...

  7. Python3基础——字符串类型

    Text Sequence Type - str(immutable) class str(object='') class str(object=b'', encoding='utf-8', err ...

  8. C#实现——十大排序算法之选择排序

    选择排序法 1.工作原理(算法思路) 给定一个待排序数组,找到数组中最小的那个元素 如果最小元素不是待排序数组的第一个元素,则将其和第一个元素互换 在剩下的元素中,重复1.2过程,直到排序完成. 2. ...

  9. 3-kubernetes监控与日志管理

    监控集群资源利用率 metrics-server是一个集群范围的资源使用情况的数据聚合器,作为一个应用部署在集群中 metrics-server从每个节点上kubelet API收集指标,通过kube ...

  10. regsvr32 bypass windows defender 新思路

    原文链接:blog 在对regsvr32的用法进行了解之后,对于Casey Smith的远程js脚本执行命令的思路很感兴趣. 命令语法如下: regsvr32 /s /n /u /i:http://1 ...