Future” 在计算机科学,尤其是在并发编程异步编程中,是一个非常核心且经典的概念。


一、定义

Future 是一个占位符,它代表一个尚未完成但将来会完成的计算结果。

你可以把它想象成一张“取餐小票”:你点完咖啡,服务员给你一张小票。这张小票不是咖啡本身,但它承诺未来你会凭此拿到咖啡。在小票有效期间(计算进行中),你可以去做其他事(不阻塞主线程),等咖啡做好了,你再凭票取咖啡(获取结果)。


二、Future 的核心状态与行为

一个典型的 Future 在生命周期中通常经历三种状态:

  1. Pending(进行中):任务正在执行,结果尚未产生。

  2. Completed(已完成)

    • Success(成功):任务正常结束,产生了有效值。

    • Failure(失败):任务抛出异常,产生了错误。

核心行为:

  • 获取结果:通常通过 .get() 或 .result() 等方法。但注意,在纯粹的异步模型中,调用 get() 会阻塞当前线程直到结果就绪。现代的非阻塞模型更倾向于通过回调组合器来处理。

  • 添加回调:如 onComplete,当 Future 完成时自动执行回调。

  • 组合变换:如 mapflatMapfilter 等,允许将多个 Future 像集合一样进行操作。


三、Future 的两种执行模式

这是初学者容易混淆的点,必须区分:

  1. 热执行(Eager Execution)

    • 一旦你创建一个 Future,任务立即在后台开始执行。

    • 如:CompletableFuture.supplyAsync()Scala FuturePython concurrent.futures.

  2. 冷执行(Lazy Execution)

    • 创建 Future 时只是定义了一个计算,并不执行。需要调用 await 或交给执行器才会执行。

    • 如:Rust FutureJava 8 StreamKotlin Flow.


四、例子

Java 8+

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

public class FutureDemo {
    
    public static void main(String[] args) {
        // 开始时间
        long start = System.currentTimeMillis();
        
        // 1. 异步获取用户
        CompletableFuture<User> userFuture = CompletableFuture.supplyAsync(() -> {
            sleep(1000); // 模拟耗时1秒
            System.out.println("线程: " + Thread.currentThread().getName() + " 获取到用户");
            return new User(1001, "张三");
        });
        
        // 2. 拿到用户后,异步获取他的订单
        CompletableFuture<Order> orderFuture = userFuture.thenCompose(user -> 
            CompletableFuture.supplyAsync(() -> {
                sleep(800); // 模拟耗时0.8秒
                System.out.println("线程: " + Thread.currentThread().getName() 
                    + " 获取到用户 " + user.getId() + " 的订单");
                return new Order(50001, user.getId(), 299.00);
            })
        );
        
        // 3. 同时查询系统配置(完全不依赖前面)
        CompletableFuture<Config> configFuture = CompletableFuture.supplyAsync(() -> {
            sleep(500); // 模拟耗时0.5秒
            System.out.println("线程: " + Thread.currentThread().getName() + " 获取到系统配置");
            return new Config("vip_discount", 0.8);
        });
        
        // 4. 等用户订单和配置都准备好,计算最终价格
        CompletableFuture<String> resultFuture = orderFuture.thenCombine(configFuture, 
            (order, config) -> {
                double finalPrice = order.getAmount() * config.getDiscount();
                return String.format("用户 %s 的订单 %d 最终价格: %.2f", 
                    userFuture.join().getName(), order.getId(), finalPrice);
            }
        );
        
        // 5. 最终结果回调
        resultFuture.whenComplete((result, error) -> {
            if (error == null) {
                System.out.println("✓ 成功: " + result);
            } else {
                System.err.println("✗ 失败: " + error.getMessage());
            }
            System.out.println("总耗时: " + (System.currentTimeMillis() - start) + "ms");
        });
        
        // 6. 主线程等待一下(否则程序直接退出了)
        sleep(2000);
    }
    
    static void sleep(long millis) {
        try {
            Thread.sleep(millis);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    static class User {
        private int id; private String name;
        User(int id, String name) { this.id = id; this.name = name; }
        int getId() { return id; }
        String getName() { return name; }
    }
    
    static class Order {
        private int id; private int userId; private double amount;
        Order(int id, int userId, double amount) { 
            this.id = id; this.userId = userId; this.amount = amount; 
        }
        int getId() { return id; }
        double getAmount() { return amount; }
    }
    
    static class Config {
        private String key; private double discount;
        Config(String key, double discount) { this.key = key; this.discount = discount; }
        double getDiscount() { return discount; }
    }
}

运行结果:

线程: ForkJoinPool.commonPool-worker-1 获取到用户
线程: ForkJoinPool.commonPool-worker-2 获取到系统配置
线程: ForkJoinPool.commonPool-worker-1 获取到用户 1001 的订单
✓ 成功: 用户 张三 的订单 50001 最终价格: 239.20
总耗时: 1023ms

Kotlin

Kotlin 推荐使用协程而不是传统的 Future。它的异步结果类型叫 Deferred<T>,可以理解为 Kotlin 版的 Future,但更轻量、更强大。

看下面这个完整的电商订单处理例子:

import kotlinx.coroutines.*
import kotlin.system.measureTimeMillis

// 数据类
data class User(val id: Int, val name: String)
data class Order(val id: Int, val userId: Int, val amount: Double)
data class Config(val key: String, val discount: Double)
data class Product(val id: Int, val name: String, val price: Double)

fun main() = runBlocking {
    println(" 开始处理订单...")
    
    val totalTime = measureTimeMillis {
        processOrder()
    }
    
    println(" 总耗时: ${totalTime}ms")
}

suspend fun processOrder() {
    coroutineScope {
        // ========== 1. 创建 Deferred(相当于 Future) ==========
        val userDeferred: Deferred<User> = async {
            fetchUser()
        }
        
        val configDeferred: Deferred<Config> = async {
            fetchConfig()
        }
        
        // ========== 2. 等待用户结果 ==========
        val user = userDeferred.await()  // 非阻塞等待
        println(" 已获取用户: ${user.name}")
        
        // ========== 3. 依赖上一个结果 ==========
        val orderDeferred: Deferred<Order> = async {
            fetchOrder(user.id)
        }
        
        // ========== 4. 并发获取商品详情 ==========
        val productsDeferred: Deferred<List<Product>> = async {
            fetchRecommendedProducts(user.id)
        }
        
        // ========== 5. 等待所有结果 ==========
        val order = orderDeferred.await()
        val config = configDeferred.await()
        val products = productsDeferred.await()
        
        // ========== 6. 组合结果 ==========
        val finalPrice = order.amount * config.discount
        
        println("""
            
             订单详情:
            - 订单号: ${order.id}
            - 用户: ${user.name}
            - 原价: ¥${order.amount}
            - 折扣: ${config.discount * 10}折
            - 最终价: ¥${"%.2f".format(finalPrice)}
            - 推荐商品: ${products.joinToString { it.name }}
        """.trimIndent())
    }
}

// 模拟耗时操作(都加了延迟)
suspend fun fetchUser(): User {
    delay(1000)  // 模拟网络请求
    println("  ✓ 用户服务: 查询完成")
    return User(1001, "张三")
}

suspend fun fetchOrder(userId: Int): Order {
    delay(800)
    println("  ✓ 订单服务: 用户 $userId 订单查询完成")
    return Order(50001, userId, 299.00)
}

suspend fun fetchConfig(): Config {
    delay(500)
    println("  ✓ 配置服务: 获取折扣配置")
    return Config("vip_discount", 0.8)
}

suspend fun fetchRecommendedProducts(userId: Int): List<Product> {
    delay(600)
    println("  ✓ 推荐服务: 获取用户 $userId 的推荐商品")
    return listOf(
        Product(1, "无线鼠标", 89.9),
        Product(2, "机械键盘", 299.0),
        Product(3, "显示器支架", 159.0)
    )
}

运行结果:

 开始处理订单...
  ✓ 配置服务: 获取折扣配置
  ✓ 用户服务: 查询完成
 已获取用户: 张三
  ✓ 订单服务: 用户 1001 订单查询完成
  ✓ 推荐服务: 获取用户 1001 的推荐商品

 订单详情:
- 订单号: 50001
- 用户: 张三
- 原价: ¥299.0
- 折扣: 8.0折
- 最终价: ¥239.20
- 推荐商品: 无线鼠标, 机械键盘, 显示器支架
 总耗时: 1023ms

Kotlin Deferred 核心用法

1. 创建 Deferred(3种方式)

// 方式1: async 构建器(最常用)
val deferred: Deferred<String> = async {
    delay(1000)
    "Hello"
}

// 方式2: CompletableDeferred(手动控制)
val completable = CompletableDeferred<String>()
// 在其他地方完成
completable.complete("World")
// 或带异常
// completable.completeExceptionally(Exception("出错了"))

// 方式3: future {}(与Java Future互操作)
val javaFuture: CompletableFuture<String> = CompletableFuture.supplyAsync { "Java" }
val kotlinDeferred: Deferred<String> = javaFuture.asDeferred()  // 扩展函数

2. 等待结果

// await() - 挂起直到结果就绪(非阻塞)
val result = deferred.await()

// awaitAll() - 等待多个
val results = awaitAll(deferred1, deferred2, deferred3)

// join() - 不关心返回值,只等完成
deferred.join()

3. 并发模式

suspend fun concurrentExample() = coroutineScope {
    // 并行执行(同时发起)
    val deferred1 = async { task1() }
    val deferred2 = async { task2() }
    val deferred3 = async { task3() }
    
    // 等待所有完成
    val (result1, result2, result3) = awaitAll(deferred1, deferred2, deferred3)
    
    // 或只等最快的那个
    val firstCompleted = select<Deferred<String>> {
        deferred1.onAwait { it }
        deferred2.onAwait { it }
    }.await()
}

 Future vs Deferred 对比

特性 Java CompletableFuture Kotlin Deferred
阻塞方式 .get() 阻塞线程 .await() 挂起协程(不阻塞线程)
内存开销 每个Future一个线程(或线程池) 极轻量,挂起无线程占用
组合语法 .thenCompose().thenCombine() 直接用 await(),像同步代码
取消 .cancel(true) .cancel()
超时 .orTimeout(1, TimeUnit.SECONDS) withTimeout(1000) { deferred.await() }
异常处理 .exceptionally() try-catch 包围 await()

 Kotlin 特有的强大模式

1. 结构化并发(自动取消)

suspend fun structuredConcurrency() = coroutineScope {
    // 如果任何一个子协程失败,所有其他子协程自动取消
    val user = async { fetchUser() }
    val order = async { fetchOrder(user.await().id) }  // 这里如果user失败,order自动取消
    
    try {
        println(order.await())
    } catch (e: Exception) {
        // user 或 order 任何一个出异常都会到这里
        println("处理失败,所有任务已取消")
    }
    // 所有async任务在这里自动完成清理
}

2. 超时控制

suspend fun withTimeoutExample() = coroutineScope {
    val deferred = async {
        delay(2000)
        "慢速任务"
    }
    
    try {
        // 最多等1秒
        withTimeout(1000) {
            val result = deferred.await()
            println(result)
        }
    } catch (e: TimeoutCancellationException) {
        println(" 超时了,自动取消")
        // deferred 自动被取消
    }
}

3. Flow - 多个值的异步流

如果 Future 代表一个异步值,那 Flow 就是多个异步值:

fun stockPrices(): Flow<Double> = flow {
    val prices = listOf(100.0, 101.5, 102.3, 101.8, 103.2)
    for (price in prices) {
        delay(1000)  // 每秒推送一次价格
        emit(price)  // 发射值
    }
}

suspend fun flowExample() {
    stockPrices()
        .map { it * 0.9 }  // 转换
        .filter { it > 90 } // 过滤
        .take(3)           // 只取前3个
        .collect { price ->
            println("当前股价: $price")
        }
}

 实战:模拟外卖订单系统

import kotlinx.coroutines.*
import kotlin.random.Random

data class OrderRequest(val foodId: Int, val address: String)
data class Payment(val orderId: String, val success: Boolean)
data class Delivery(val orderId: String, val estimatedTime: Int)

suspend fun main() = runBlocking {
    println(" 外卖系统启动...\n")
    
    val orders = listOf(
        OrderRequest(101, "北京市朝阳区"),
        OrderRequest(102, "上海市浦东新区"),
        OrderRequest(103, "广州市天河区")
    )
    
    val startTime = System.currentTimeMillis()
    
    // 并发处理多个订单
    val results = orders.map { order ->
        async {
            processOrder(order)
        }
    }.awaitAll()
    
    println("\n 所有订单处理完成,总耗时: ${System.currentTimeMillis() - startTime}ms")
    results.forEachIndexed { index, result ->
        println("订单${index + 1}: $result")
    }
}

suspend fun processOrder(request: OrderRequest): String = coroutineScope {
    println(" 开始处理订单: ${request.foodId}")
    
    // 1. 并行执行:支付和餐厅备餐
    val paymentDeferred = async { 
        processPayment(request) 
    }
    
    val restaurantDeferred = async { 
        prepareFood(request.foodId) 
    }
    
    // 2. 等待支付和备餐都完成
    val payment = paymentDeferred.await()
    val food = restaurantDeferred.await()
    
    if (!payment.success) {
        return@coroutineScope " 支付失败"
    }
    
    // 3. 开始配送
    val delivery = async {
        dispatchDelivery(request.address)
    }.await()
    
    " 已送达,${food},预计${delivery.estimatedTime}分钟"
}

suspend fun processPayment(request: OrderRequest): Payment {
    delay(500)  // 模拟支付处理
    return Payment(
        orderId = "ORD${Random.nextInt(1000, 9999)}",
        success = Random.nextDouble() > 0.1  // 90%成功率
    )
}

suspend fun prepareFood(foodId: Int): String {
    delay(800)  // 模拟备餐
    return when (foodId) {
        101 -> "汉堡套餐"
        102 -> "披萨"
        103 -> "寿司"
        else -> "未知美食"
    }
}

suspend fun dispatchDelivery(address: String): Delivery {
    delay(600)  // 模拟找骑手
    return Delivery(
        orderId = "DEL${Random.nextInt(1000, 9999)}",
        estimatedTime = Random.nextInt(20, 40)
    )
}

 关键总结

  1. Kotlin 的 Deferred = 协程版的 Future,用 async 创建,await() 等待

  2. 不阻塞线程await() 是挂起点,不是阻塞点

  3. 结构化并发coroutineScope 自动管理生命周期,取消会传播

  4. 比 Java Future 更轻量:10万个并发任务也没问题

  5. 语法更简洁:不用写一长串链式调用,直接 val result = deferred.await()

什么时候用 async

  • 需要并发执行多个独立任务

  • 需要等待结果并继续处理

  • 任务之间有依赖关系

什么时候不用?

  • 顺序执行 → 直接 suspend fun 挨个调用

  • 不需要返回值 → 用 launch

  • 多个异步值 → 用 Flow

这就是 Kotlin 风格的 Future,既保留了异步非阻塞的优点,又让代码像同步一样直观。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐