Java利用future及时获取多线程运行结果

作者:clare-chen 时间:2022-02-18 21:57:30 

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

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

这里有一种更好的方式来实现对任意一个线程运行完成后的结果都能及时获取的办法:使用CompletionService,它内部添加了阻塞队列,从而获取future中的值,然后根据返回值做对应的处理。一般future使用和CompletionService使用的两个测试案例如下:


import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* 多线程执行,异步获取结果
*
* @author i-clarechen
*
*/
public class AsyncThread {
 public static void main(String[] args) {
   AsyncThread t = new AsyncThread();
   List<Future<String>> futureList = new ArrayList<Future<String>>();
   t.generate(3, futureList);
   t.doOtherThings();
   t.getResult(futureList);
 }
 /**
  * 生成指定数量的线程,都放入future数组
  *
  * @param threadNum
  * @param fList
  */
 public void generate(int threadNum, List<Future<String>> fList) {
   ExecutorService service = Executors.newFixedThreadPool(threadNum);
   for (int i = 0; i < threadNum; i++) {
     Future<String> f = service.submit(getJob(i));
     fList.add(f);
   }
   service.shutdown();
 }
 /**
  * other things
  */
 public void doOtherThings() {
   try {
     for (int i = 0; i < 3; i++) {
       System.out.println("do thing no:" + i);
       Thread.sleep(1000 * (new Random().nextInt(10)));
     }
   } catch (InterruptedException e) {
     e.printStackTrace();
   }
 }
 /**
  * 从future中获取线程结果,打印结果
  *
  * @param fList
  */
 public void getResult(List<Future<String>> fList) {
   ExecutorService service = Executors.newSingleThreadExecutor();
   service.execute(getCollectJob(fList));
   service.shutdown();
 }
 /**
  * 生成指定序号的线程对象
  *
  * @param i
  * @return
  */
 public Callable<String> getJob(final int i) {
   final int time = new Random().nextInt(10);
   return new Callable<String>() {
     @Override
     public String call() throws Exception {
       Thread.sleep(1000 * time);
       return "thread-" + i;
     }
   };
 }
 /**
  * 生成结果收集线程对象
  *
  * @param fList
  * @return
  */
 public Runnable getCollectJob(final List<Future<String>> fList) {
   return new Runnable() {
     public void run() {
       for (Future<String> future : fList) {
         try {
           while (true) {
             if (future.isDone() && !future.isCancelled()) {
               System.out.println("Future:" + future
                   + ",Result:" + future.get());
               break;
             } else {
               Thread.sleep(1000);
             }
           }
         } catch (Exception e) {
           e.printStackTrace();
         }
       }
     }
   };
 }
}

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


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

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


import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletionService;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingDeque;
public class testCallable {
 public static void main(String[] args) {
   try {
     completionServiceCount();
   } catch (InterruptedException e) {
     e.printStackTrace();
   } catch (ExecutionException e) {
     e.printStackTrace();
   }
 }
 /**
  * 使用completionService收集callable结果
  * @throws ExecutionException
  * @throws InterruptedException
  */
 public static void completionServiceCount() throws InterruptedException, ExecutionException {
   ExecutorService executorService = Executors.newCachedThreadPool();
   CompletionService<Integer> completionService = new ExecutorCompletionService<Integer>(
       executorService);
   int threadNum = 5;
   for (int i = 0; i < threadNum; i++) {
     completionService.submit(getTask(i));
   }
   int sum = 0;
   int temp = 0;
   for(int i=0;i<threadNum;i++){
     temp = completionService.take().get();
     sum += temp;
     System.out.print(temp + "\t");
   }
   System.out.println("CompletionService all is : " + sum);
   executorService.shutdown();
 }
 public static Callable<Integer> getTask(final int no) {
   final Random rand = new Random();
   Callable<Integer> task = new Callable<Integer>() {
     @Override
     public Integer call() throws Exception {
       int time = rand.nextInt(100)*100;
       System.out.println("thead:"+no+" time is:"+time);
       Thread.sleep(time);
       return no;
     }
   };
   return task;
 }
}

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


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

来源:http://www.cnblogs.com/clarechen/p/4604189.html

标签:java,多线程,future
0
投稿

猜你喜欢

  • C# 解决datagridview控件显示大量数据拖拉卡顿问题

    2022-03-21 12:52:24
  • 利用C#实现获取当前设备硬件信息

    2022-09-11 07:15:37
  • Java实现角色扮演游戏的示例代码

    2023-03-31 19:41:45
  • 浅析java中的取整(/)和求余(%)

    2023-04-30 23:46:23
  • Java后台通过Collections获取list集合中最大数,最小数代码

    2023-03-15 19:53:05
  • java多线程读取多个文件的方法

    2022-12-05 04:37:45
  • Maven install 报错"程序包不存在"问题的解决方法

    2021-05-27 06:08:06
  • Java中List.of()和Arrays.asList()的区别及原因分析

    2023-08-06 00:33:16
  • Java统计输入字符的英文字母、空格、数字和其它

    2022-11-13 04:11:31
  • java读写oracle的blob字段示例

    2023-12-22 16:19:00
  • Android 第三方应用接入微信平台研究情况分享(二)

    2022-01-20 10:10:38
  • Java性能优化技巧汇总

    2023-01-05 16:26:31
  • 生成8位随机不重复的数字编号的方法

    2023-11-26 07:00:29
  • 浅谈Java中IO和NIO的本质和区别

    2023-11-01 01:44:08
  • 浅谈自定义校验注解ConstraintValidator

    2023-07-06 03:10:53
  • kafka消费不到数据的排查过程

    2023-11-14 04:35:30
  • java8 如何实现分组计算数量和计算总数

    2022-05-05 01:17:32
  • Android View与Compose互相调用实例探究

    2021-06-11 09:07:29
  • WCF实现的计算器功能实例

    2022-05-07 23:17:12
  • C#几种截取字符串的方法小结

    2023-07-16 09:55:10
  • asp之家 软件编程 m.aspxhome.com