C++11中std::future的使用详解和实战示例

在 C++11 中,std::future 是标准库中的一个强大工具,用于实现异步任务获取返回值。它与 std::asyncstd::promise 搭配使用,能够从并发任务中安全获取结果,是线程通信和异步执行的核心组件之一。


一、std::future 是什么?

  • 它表示一个异步操作的结果,用于获取尚未完成任务的值。
  • 通常与 std::asyncstd::promise 搭配使用。
  • std::future:未来某个时间点将拥有一个类型为 T 的结果。

二、典型使用场景

场景一:std::async + std::future(最常见,简单)

异步执行一个函数,主线程稍后使用 future.get() 获取其结果。

场景二:std::promise + std::future(手动控制结果传递)

适用于线程中产生结果、异常或信号时主动传递给主线程。


三、基础示例(使用 std::async

#include 
#include 
#include 

// 一个耗时函数
int slow_add(int a, int b) {
    std::this_thread::sleep_for(std::chrono::seconds(2));
    return a + b;
}

int main() {
    std::cout << "Starting async task...\n";

    // 启动异步任务,立即返回 std::future 对象
    std::future<int> result = std::async(std::launch::async, slow_add, 3, 4);

    std::cout << "Doing other work...\n";

    // 等待结果并获取(阻塞)
    int value = result.get();

    std::cout << "Result: " << value << std::endl;
    return 0;
}

输出:

Starting async task...
Doing other work...
Result: 7

四、控制异步启动策略

std::future<int> f1 = std::async(std::launch::async, func);   // 异步立即启动线程
std::future<int> f2 = std::async(std::launch::deferred, func); // 延迟执行(在 get() 时运行)
std::future<int> f3 = std::async(std::launch::async | std::launch::deferred, func); // 默认行为

五、std::promise 搭配 std::future

#include 
#include 
#include 

void calculate(std::promise<int> p) {
    std::this_thread::sleep_for(std::chrono::seconds(2));
    p.set_value(42);  // 设置结果
}

int main() {
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();  // 获取 future

    std::thread t(calculate, std::move(prom));  // 线程中设置值

    std::cout << "Waiting for result..." << std::endl;
    int result = fut.get();  // 阻塞等待结果

    std::cout << "Result: " << result << std::endl;
    t.join();
    return 0;
}

六、常用函数说明

函数名 功能说明
future.get() 获取结果,阻塞直到就绪(只能调用一次)
future.wait() 阻塞直到任务完成
future.wait_for(dur) 超时等待
future.wait_until(tp) 等待到指定时间点
future.valid() 判断是否持有共享状态

七、注意事项

  • std::future::get() 只能调用一次,之后对象就失效(invalid)。
  • async 的函数抛出异常,该异常会被捕获,并在 get() 时重新抛出。
  • std::future 不是线程安全的:多个线程不能同时访问同一个 future

八、进阶示例:多个任务并发执行并获取结果

#include 
#include 
#include 

int work(int id) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100 * id));
    return id * id;
}

int main() {
    std::vector<std::future<int>> results;

    for (int i = 1; i <= 5; ++i) {
        results.push_back(std::async(std::launch::async, work, i));
    }

    for (auto& fut : results) {
        std::cout << "Result: " << fut.get() << std::endl;
    }

    return 0;
}

九、数据预处理并行化综合示例

应用场景示例:点云数据批量预处理(并发执行)

假设有大量点云块(或图像帧)需要执行滤波、去噪、下采样等操作,顺序执行较慢。可以使用 std::async 启动多个线程并行处理每个数据块。


示例代码:点云块并行处理

#include 
#include 
#include 
#include 
#include 

// 假设每个点云块是一个 vector
using PointCloudBlock = std::vector<float>;

// 模拟预处理函数(如滤波、下采样等)
PointCloudBlock preprocessBlock(const PointCloudBlock& input, int blockId) {
    std::this_thread::sleep_for(std::chrono::milliseconds(100)); // 模拟耗时
    PointCloudBlock result = input;
    for (auto& p : result) {
        p *= 0.9f; // 模拟处理
    }
    std::cout << "Block " << blockId << " processed\n";
    return result;
}

int main() {
    const int blockCount = 8;

    // 模拟 8 个点云块
    std::vector<PointCloudBlock> inputBlocks(blockCount, PointCloudBlock(1000, 1.0f));

    std::vector<std::future<PointCloudBlock>> futures;

    // 并发预处理每个块
    for (int i = 0; i < blockCount; ++i) {
        futures.push_back(std::async(std::launch::async, preprocessBlock, inputBlocks[i], i));
    }

    // 收集结果
    std::vector<PointCloudBlock> processedBlocks;
    for (auto& fut : futures) {
        processedBlocks.push_back(fut.get());
    }

    std::cout << "All blocks processed.\n";
    return 0;
}

多线程处理的好处

优点 说明
提高吞吐 并发预处理多个任务,CPU 多核资源充分利用
无需额外线程池 使用 std::async 自动调度线程
支持异常处理 若某个任务异常,future.get() 时可捕获
易于封装 可以包装为模块,适用于图像/点云/文本等任意数据

十、小结:何时用 future

  • 想让线程返回值给主线程。
  • 延迟执行某个任务。
  • 需要对异步任务的结果、超时、异常处理
  • 实现任务通信(如 promise 设置结果、主线程读取)。

你可能感兴趣的:(C++,c++,开发语言,线程通信和异步执行,多线程任务开发,C++中future使用,C++标准库,人工智能)