Java 并发编程 Future及CompletionService

简介: Java 并发编程 Future及CompletionService`Future`用于异步结果计算。它提供了一些方法来检查计算是否完成,使用`get`方法将阻塞线程直到结果返回`CompletionService`整合了`Executor`和`BlockingQueue`的功能。将`Callable`任务提交给它去执行,使用`take()`和`poll()`获取最新完成的任务执行结果.

Future

Future用于异步结果计算。它提供了一些方法来检查计算是否完成,使用get方法将阻塞线程直到结果返回

  • cancel:尝试取消任务的执行,如果任务已完成或已取消,此操作无效
  • isCancelled:任务是否已取消
  • isDone:任务是否已完成
  • get:阻塞线程以获取计算结果,直至任务执行完毕返回结果
  • get(long timeout, TimeUnit unit):阻塞线程以获取计算结果,若在指定时间没返回结果,则返回null
public  interface  Future<V> {
   
   
    boolean cancel(boolean  mayInterruptIfRunning);
    boolean isCancelled();
    boolean isDone();
    V get() throws InterruptedException, ExecutionException;
    V get(long timeout, TimeUnit unit)
        throws InterruptedException, ExecutionException, TimeoutException;
}

Future结合线程池的使用

public void futureTest(){
   
   
    ExecutorService executorService = Executors.newFixedThreadPool(10);

    Future<String> nickFuture = executorService.submit(() -> userService.getNick());
    Future<String> nameFuture = executorService.submit(() -> userService.getUserName());

    // 阻塞开始,等待结果
    String nick = nickFuture.get(1000, TimeUnit.MILLISECONDS);
    String name = nameFuture.get();
}

CompletionService

CompletionService整合了ExecutorBlockingQueue的功能。将Callable任务提交给它去执行,使用take()poll()获取最新完成的任务执行结果.

ExecutorCompletionService是该接口的实现类,内部有一个线程池和BlockingQueue队列。它的实现原理其实挺简单:每个提交给ExecutorCompletionService的任务,都会被封装成一个QueueingFutureFutureTask的子类),它重写了done()方法(该方法会在任务执行完成之后回调),将执行完成的FutureTask加入到内部队列,take()poll()将得到最新完成的结果FutrueTask

使用方法

注:若线程池为局部变量,使用完后需关闭线程池。或直接使用全局变量命名的线程池

public Map<Long, List<String>> batchDoGetLiveRecord(List<LiveRecordReqDTO> reqList) {
   
   
    Map<Long, List<String>> recordMap = Maps.newHashMap();
    // 用线程池executor新建一个CompletionService
    CompletionService<Map<Long, List<String>>> completionService = new ExecutorCompletionService<>(executor);

    try {
   
   
        for (LiveRecordReqDTO req : reqList) {
   
   
            completionService.submit(() -> doGetLiveRecordAsMap(req));
        }

        for (int i = 0; i < reqList.size(); i++){
   
   
            Map<Long, List<String>> map = completionService.take().get(1000, TimeUnit.MILLISECONDS);
            recordMap.putAll(map);
        }
    } catch (Exception e) {
   
   
        logger.warn("batchDoGetLiveRecord fail, uidList:{}, bizId:{}",reqList, bizId, e);
    } finally {
   
   
        completionService.shutdown();
    }

    return recordMap;
}

类图自[CompletionService和ExecutorCompletionService详解](https://imgconvert.csdnimg.cn/aHR0cHM6Ly93d3cuamlhbnNodS5jb20vcC9jZmRhNzA4YTM0Nzg?x-oss-process=image/format,png)
类图自CompletionService和ExecutorCompletionService详解


参考资料:

  1. CompletionService和ExecutorCompletionService详解
  2. 并发处理利器-CompletionService
相关文章
|
1天前
|
安全 Java 数据库
Java并发编程:最佳实践与性能优化
Java并发编程:最佳实践与性能优化
|
2天前
|
Java 数据处理 调度
Java多线程编程入门指南
Java多线程编程入门指南
|
2天前
|
传感器 数据采集 监控
Java串口编程入门
Java串口编程入门
|
1天前
|
前端开发 Java 开发工具
Java GUI编程:跨平台应用的设计与开发
Java GUI编程:跨平台应用的设计与开发
|
1天前
|
设计模式 Java 容器
Java多线程编程中的设计模式与挑战
Java多线程编程中的设计模式与挑战
|
1天前
|
Java API 数据库
深研Java异步编程:CompletableFuture与反应式编程范式的融合实践
【6月更文挑战第30天】Java 8的CompletableFuture革新了异步编程,提供如thenApply等流畅接口,而Java 9后的反应式编程(如Reactor)强调数据流和变化传播,以事件驱动应对高并发。两者并非竞争关系,而是互补,通过Flow API和第三方库结合,如将CompletableFuture转换为Mono进行反应式处理,实现更高效、响应式的系统设计。开发者可根据需求灵活选用,提升现代Java应用的并发性能。
14 1
|
1天前
|
安全 Java 程序员
深入理解Java内存模型(JMM)及其对并发编程的影响
【6月更文挑战第29天】在Java并发编程的世界中,内存模型是基石之一。本文将深入探讨Java内存模型(JMM)的核心概念,包括可见性、原子性、有序性和同步,并解释它们如何影响并发编程实践。通过分析JMM的工作原理和它与Java并发库的关系,我们将揭示正确使用JMM原则可以如何避免并发编程中的常见陷阱。
|
1天前
|
安全 Java
Java多线程编程实践中的常见问题与解决方案
Java多线程编程实践中的常见问题与解决方案
|
2天前
|
安全 Java 开发者
Java并发编程中的线程安全策略
在现代软件开发中,Java语言的并发编程特性使得多线程应用成为可能。然而,随着线程数量的增加,如何确保数据的一致性和系统的稳定性成为开发者面临的挑战。本文将探讨Java并发编程中实现线程安全的几种策略,包括同步机制、volatile关键字的使用、以及java.util.concurrent包提供的工具类,旨在为Java开发者提供一系列实用的方法来应对并发问题。
9 0