Future接口是Java标准API的一部分,在java.util.concurrent包中。Future接口是Java线程Future模式的实现,可以来进行异步计算。

有了Future就可以进行三段式的编程了,1.启动多线程任务2.处理其他事3.收集多线程任务结果。从而实现了非阻塞的任务调用。在途中遇到一个问题,那就是虽然能异步获取结果,但是Future的结果需要通过isdone来判断是否有结果,或者使用get()函数来阻塞式获取执行结果。这样就不能实时跟踪其他线程的结果状态了,所以直接使用get还是要慎用,最好配合isdone来使用。如果直接使用get来获取结果, get是阻塞操作, 相当于获取结果仍然是同步.因此在获取结果的时候需要注意.

  1. import java.util.ArrayList;
  2. import java.util.List;
  3. import java.util.Random;
  4. import java.util.concurrent.Callable;
  5. import java.util.concurrent.ExecutorService;
  6. import java.util.concurrent.Executors;
  7. import java.util.concurrent.Future;
  8.  
  9. /**
  10. * 多线程执行,异步获取结果
  11. *
  12. * @author i-clarechen
  13. *
  14. */
  15. public class AsyncThread {
  16.  
  17. public static void main(String[] args) {
  18. AsyncThread t = new AsyncThread();
  19. List<Future<String>> futureList = new ArrayList<Future<String>>();
  20. t.generate(3, futureList);
  21. t.doOtherThings();
  22. t.getResult(futureList);
  23. }
  24.  
  25. /**
  26. * 生成指定数量的线程,都放入future数组
  27. *
  28. * @param threadNum
  29. * @param fList
  30. */
  31. public void generate(int threadNum, List<Future<String>> fList) {
  32. ExecutorService service = Executors.newFixedThreadPool(threadNum);
  33. for (int i = 0; i < threadNum; i++) {
  34. Future<String> f = service.submit(getJob(i));
  35. fList.add(f);
  36. }
  37. service.shutdown();
  38. }
  39.  
  40. /**
  41. * other things
  42. */
  43. public void doOtherThings() {
  44. try {
  45. for (int i = 0; i < 3; i++) {
  46. System.out.println("do thing no:" + i);
  47. Thread.sleep(1000 * (new Random().nextInt(10)));
  48. }
  49. } catch (InterruptedException e) {
  50. e.printStackTrace();
  51. }
  52. }
  53.  
  54. /**
  55. * 从future中获取线程结果,打印结果
  56. *
  57. * @param fList
  58. */
  59. public void getResult(List<Future<String>> fList) {
  60. ExecutorService service = Executors.newSingleThreadExecutor();
  61. service.execute(getCollectJob(fList));
  62. service.shutdown();
  63. }
  64.  
  65. /**
  66. * 生成指定序号的线程对象
  67. *
  68. * @param i
  69. * @return
  70. */
  71. public Callable<String> getJob(final int i) {
  72. final int time = new Random().nextInt(10);
  73. return new Callable<String>() {
  74. @Override
  75. public String call() throws Exception {
  76. Thread.sleep(1000 * time);
  77. return "thread-" + i;
  78. }
  79. };
  80. }
  81.  
  82. /**
  83. * 生成结果收集线程对象
  84. *
  85. * @param fList
  86. * @return
  87. */
  88. public Runnable getCollectJob(final List<Future<String>> fList) {
  89. return new Runnable() {
  90. public void run() {
  91. for (Future<String> future : fList) {
  92. try {
  93. while (true) {
  94. if (future.isDone() && !future.isCancelled()) {
  95. System.out.println("Future:" + future
  96. + ",Result:" + future.get());
  97. break;
  98. } else {
  99. Thread.sleep(1000);
  100. }
  101. }
  102. } catch (Exception e) {
  103. e.printStackTrace();
  104. }
  105. }
  106. }
  107. };
  108. }
  109.  
  110. }
    优化获取方式:
  1.       List<Object> results = null;
  2. int retryLimit = 3;
  3. long delay = 10;
  4. int tryTime = 0;
  5.     for(Future future : futures)
  6. do {
  7. try {
  8. //此处原理:
  9. results = future.get();
  10. } catch (Exception e) {
  11. results = null;
  12. }
  13. tryTime++;
  14. if (results == null) {
  15. try {
  16. Thread.sleep(delay << tryTime);
  17. } catch (InterruptedException e) {
  18. }
  19. }
  20. } while (results == null && tryTime < retryLimit);
  21.     }
  22. return results;

运行结果打印和future放入列表时的顺序一致,为0,1,2:

  1. do thing no:0
  2. do thing no:1
  3. do thing no:2
  4. Future:java.util.concurrent.FutureTask@68e1ca74,Result:thread-0
  5. Future:java.util.concurrent.FutureTask@3fb2bb77,Result:thread-1
  6. Future:java.util.concurrent.FutureTask@6f31a24c,Result:thread-2

使用CompletionService,它内部添加了阻塞队列,从而获取future中的值,然后根据返回值做对应的处理

下面是先执行完的线程先处理的方案:

  1. import java.util.Random;
  2. import java.util.concurrent.BlockingQueue;
  3. import java.util.concurrent.Callable;
  4. import java.util.concurrent.CompletionService;
  5. import java.util.concurrent.ExecutionException;
  6. import java.util.concurrent.ExecutorCompletionService;
  7. import java.util.concurrent.ExecutorService;
  8. import java.util.concurrent.Executors;
  9. import java.util.concurrent.Future;
  10. import java.util.concurrent.LinkedBlockingDeque;
  11.  
  12. public class testCallable {
  13. public static void main(String[] args) {
  14. try {
  15. completionServiceCount();
  16. } catch (InterruptedException e) {
  17. e.printStackTrace();
  18. } catch (ExecutionException e) {
  19. e.printStackTrace();
  20. }
  21. }
  22.  
  23. /**
  24. * 使用completionService收集callable结果
  25. * @throws ExecutionException
  26. * @throws InterruptedException
  27. */
  28. public static void completionServiceCount() throws InterruptedException, ExecutionException {
  29. ExecutorService executorService = Executors.newCachedThreadPool();
  30. CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(
  31. executorService);
  32. int threadNum = 5;
  33. for (int i = 0; i < threadNum; i++) {
  34. completionService.submit(getTask(i));
  35. }
  36. int sum = 0;
  37. int temp = 0;
  38. for(int i=0;i<threadNum;i++){
  39. temp = completionService.take().get();
  40. sum += temp;
  41. System.out.print(temp + "\t");
  42. }
  43. System.out.println("CompletionService all is : " + sum);
  44. executorService.shutdown();
  45. }
  46.  
  47. public static Callable<Integer> getTask(final int no) {
  48. final Random rand = new Random();
  49. Callable<Integer> task = new Callable<Integer>() {
  50. @Override
  51. public Integer call() throws Exception {
  52. int time = rand.nextInt(100)*100;
  53. System.out.println("thead:"+no+" time is:"+time);
  54. Thread.sleep(time);
  55. return no;
  56. }
  57. };
  58. return task;
  59. }
  60. }

运行结果为最先结束的线程结果先被处理:

  1. thead:0 time is:4200
  2. thead:1 time is:6900
  3. thead:2 time is:2900
  4. thead:3 time is:9000
  5. thead:4 time is:7100
  6. 2 0 1 4 3 CompletionService all is : 10

java中异步调用注意的更多相关文章

  1. java中异步调用的解决方法

    package demo.future; import java.util.ArrayList; import java.util.List; import java.util.concurrent. ...

  2. 在Java中直接调用js代码(转载)

    http://blog.csdn.net/xzyxuanyuan/article/details/8062887 JDK1.6版添加了新的ScriptEngine类,允许用户直接执行js代码. 在Ja ...

  3. 在Java中直接调用js代码

    JDK1.6版添加了新的ScriptEngine类,允许用户直接执行js代码. 在Java中直接调用js代码 不能调用浏览器中定义的js函数,会抛出异常提示ReferenceError: “alert ...

  4. 利用回调实现Java的异步调用

    异步是指调用发出后,调用者不会立刻得到结果,而是在调用发出后,被调用者通知调用者,或通过回调函数处理这个调用. 回调简单地说就是B中有一个A,这样A在调用B的某个方法时实际上是调用到了自己的方法. 利 ...

  5. Java中如何调用静态方法

    Java中如何调用静态方法: 1.如果想要调用的静态方法在本类中,可直接使用方法名调用 2.调用其他类的静态方法,可使用类名.方法名调用 关于静态方法能被什么调用 1.实例方法 2.静态发放

  6. java实现异步调用实例

    在JAVA平台,实现异步调用的角色有如下三个角色: 调用者 取货凭证   真实数据 一个调用者在调用耗时操作,不能立即返回数据时,先返回一个取货凭证.然后在过一断时间后凭取货凭证来获取真正的数据.  ...

  7. Java中异步注解@Async的陷阱

    或许,你在Java后端添加异步过程时会这样处理,然后摇摇大摆.灰溜溜地闪,而实际的运行结果却并不是我们期望的那样.那么,现在就将试验结果记录如下,以便少走弯路. (一)在Controller层的公开接 ...

  8. Oracle存储过程中异步调用的实际操作步骤

    本文标签:Oracle存储过程 我们都知道在Oracle数据库的实际应用的过程中,我们经常把相关的业务处理逻辑,放在Oracle存储过程中,客户端以通过ADO来进行相关的调用  .而有些相关的业务逻辑 ...

  9. java中如何调用oracle存储过程

    在java中使用CallableStatement调用存储过程 列: 创建需要的测试表:create table Test(tid varchar2(10),tname varchar2(10)): ...

随机推荐

  1. Ubuntu下重启mysql

    启动mysql: 方式一:sudo /etc/init.d/mysql start 方式二:sudo service mysql start 停止mysql: 方式一:sudo /etc/init.d ...

  2. 何为JavaScript原型?读完你就明白了

    熟悉软件开发的朋友都知道,原型是产品或数据系统的一个基本的实用模型,通常为示范目的或开发程序的部份结构.原型的重要性不言而喻,接下来我就会为你讲解关于JavaScript中的原型概念.原型对象释义每一 ...

  3. Linux Docker Introduction

    Setup on Ubuntu. 前提条件: Docker需要两个重要的安装要求: 它仅适用于64位Linux安装,注意:是64位的Linux系统. 它需要Linux内核版本3.10或更高版本. 要查 ...

  4. Word 去除文字底纹

    有时候从网页复制的文字有底纹,如何清除呢? 未完 ...... 点击访问原文(进入后根据右侧标签,快速定位到本文)

  5. 什么是PHP?

    PHP起源于1995年,由Rasmus Lerdorf开发.到现在,PHP已经历了21年的时间洗涤,成为全球最受欢迎的脚本开发语言之一.由于PHP 5是一种面向对象.完全跨平台的新型Web开发语言.所 ...

  6. mysql 注意小结

    char 默认是1 个字符 char(12) 设置是12个字符 不管是中文还是英文或者数字只能有十二个 设置外键时,这时候外键对应的父键的字段要是主键 非空而且是唯一. create table t1 ...

  7. Zookeeper的典型应用场景(转)

    在寒假前,完成了Zookeeper系列的前5篇文章,主要是分布式的相关理论,包括CAP,BASE理论,分布式数据一致性算法:2PC,3PC,Paxos算法,Zookeeper的相关基本特性,ZAB协议 ...

  8. CentOS7搭建jenkins

    一.概述 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 安装环境 操作系统:centos ...

  9. OpenFace 调试记录

    1.OpenFace 是 卡耐基梅陇(CMU)大学的一个图像+机器学习项目,整体程序包含:人脸发现,特征提取,特征神经网络训练,人脸识别这四部分. github   https://github.co ...

  10. 2019 携程旅行网java面试笔试题 (含面试题解析)

      本人5年开发经验.18年年底开始跑路找工作,在互联网寒冬下成功拿到阿里巴巴.今日头条.蚂蚁金服等公司offer,岗位是Java后端开发,因为发展原因最终选择去了携程,入职一年时间了,也成为了面试官 ...