Bohr-L Bohr-L
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

刘博

I'm a slow walker, But I never walk backwards.
首页
技术
常见面试题
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 数据处理与存储类

  • Spring 生态类

  • 缓存问题类

  • 多线程类

    • 多线程 Future 的用法
    • JVM 类

    • MySQL 类

    • Java 8 + 特性类

    • 其他技术类

    • 常见面试题
    • 多线程类
    刘博
    2025-12-28
    目录

    多线程 Future 的用法

    在 Java 中,Future是 “异步任务的结果容器”,用于获取多线程异步执行的结果。当提交一个任务到线程池时,会返回一个Future对象,通过该对象可判断任务是否完成、获取任务结果、取消任务,解决了 “主线程等待子线程完成” 的低效问题。

    # 1. 核心接口与类

    • Future:核心接口,定义 4 个关键方法:
      • V get():阻塞等待任务完成,返回任务结果(若任务被取消,抛出CancellationException;若任务异常,抛出ExecutionException);
      • V get(long timeout, TimeUnit unit):带超时的get(),超时未完成则抛出TimeoutException;
      • boolean isDone():判断任务是否已完成(正常完成、异常、取消均返回true);
      • boolean cancel(boolean mayInterruptIfRunning):取消任务,mayInterruptIfRunning=true表示若任务正在执行,中断线程;false表示仅取消未执行的任务。
    • FutureTask:Future的实现类,同时实现Runnable接口,可作为任务提交到线程池,也可直接用Thread启动。
    • CompletableFuture:Java 8 新增,增强Future功能,支持链式调用、异步回调、异常处理,解决了Future需阻塞获取结果的问题(推荐使用)。

    # 2. 常见用法示例

    # (1)基础用法:通过线程池获取 Future

    java 运行

    import java.util.concurrent.*;
    
    public class FutureDemo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            // 1. 创建线程池
            ExecutorService executor = Executors.newFixedThreadPool(1);
            
            // 2. 提交任务,返回Future
            Future<Integer> future = executor.submit(() -> {
                // 模拟异步任务(如计算、查数据库)
                Thread.sleep(2000);
                return 1 + 1; // 任务结果
            });
            
            // 3. 主线程可做其他事情(非阻塞)
            System.out.println("主线程执行其他任务...");
            
            // 4. 获取任务结果(阻塞,直到任务完成)
            Integer result = future.get();
            System.out.println("异步任务结果:" + result); // 输出:2
            
            // 5. 关闭线程池
            executor.shutdown();
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    # (2)带超时的 get ():避免无限阻塞

    java 运行

    try {
        // 超时时间2秒,超过则抛出TimeoutException
        Integer result = future.get(2, TimeUnit.SECONDS);
    } catch (TimeoutException e) {
        System.out.println("任务超时,取消任务");
        future.cancel(true); // 取消任务
    }
    
    1
    2
    3
    4
    5
    6
    7
    # (3)FutureTask:直接用 Thread 启动

    java 运行

    public class FutureTaskDemo {
        public static void main(String[] args) throws ExecutionException, InterruptedException {
            // 1. 创建FutureTask(包装任务)
            FutureTask<String> futureTask = new FutureTask<>(() -> {
                Thread.sleep(1000);
                return "FutureTask任务完成";
            });
            
            // 2. 用Thread启动任务
            new Thread(futureTask).start();
            
            // 3. 获取结果
            String result = futureTask.get();
            System.out.println(result); // 输出:FutureTask任务完成
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    # (4)CompletableFuture:异步回调(推荐)

    java 运行

    import java.util.concurrent.CompletableFuture;
    
    public class CompletableFutureDemo {
        public static void main(String[] args) throws InterruptedException {
            // 1. 异步执行任务,无需线程池(默认用ForkJoinPool)
            CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                return "CompletableFuture任务完成";
            });
            
            // 2. 异步回调(任务完成后自动执行,无需阻塞)
            future.thenAccept(result -> System.out.println("回调结果:" + result));
            
            // 3. 主线程等待(防止程序提前退出)
            Thread.sleep(2000);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    # 3. 注意事项

    • get () 方法阻塞:Future.get()会阻塞主线程,若任务执行时间长,会影响主线程效率,推荐用CompletableFuture的异步回调替代;
    • 任务取消:cancel(true)会中断正在执行的任务,需确保任务能响应中断(如在Thread.sleep()、wait()时会抛出InterruptedException);
    • 异常处理:get()会将任务中的异常包装为ExecutionException,需通过e.getCause()获取原始异常;CompletableFuture可通过exceptionally()处理异常(如future.exceptionally(e -> "默认值"));
    • 线程池关闭:提交任务到线程池后,需调用executor.shutdown()关闭线程池,避免线程泄漏。

    上次更新: 12/30/2025
    设计 Redis 的 key 和 value ,有哪些原则?
    JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的

    ← 设计 Redis 的 key 和 value ,有哪些原则? JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的→

    最近更新
    01
    CPU 使用率较高排查和解决
    12-29
    02
    JVM OOM 问题如何排查和解决
    12-29
    03
    接口防刷怎么实现?
    12-29
    更多文章>
    Theme by Vdoing | Copyright © 2025-2026 Bohr-L's note
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式