多线程程序设计(九)——Future

本文摘要了《Java多线程设计模式》一书中提及的 Future 模式的适用场景,并针对书中例子(若干名称有微调)给出一份 C++ 参考实现及其 UML 逻辑图,也列出与之相关的模式。

◆ 适用场景

当前线程将某个函数调用委托给其它线程去完成,自己可以继续后面的处理。仅在需要结果时才去获取被委托的函数的执行结果。

◆ 解决方案

将委托的函数作为 std::async 的启动函数。在需要结果时,调用 std::async 的返回对象 future 的 get() 函数,即可获取被委托的函数的执行结果。

◆ 参考实现

例子模拟了用例向主机(Host)发送请求后,过一会儿再要求获取请求结果(Data)的过程。

class Data
{

    ...

    string
    get_content()
    {
        return __content__;
    }

};


class Host
{

    ...

    future<Data>
    request(int count, char c)
    {
        ...
        future<Data> f = std::async(launch::deferred | launch::async,
                                    [=]() -> Data {
                                        for (int i = 0; i < count; ++i)
                                            std::this_thread::sleep_for(milliseconds(100));
                                        return Data(count, c);
                                    });

        ...

        return f;
    }

};

std::async 使用 async 或 deferred 的启动策略,启动 lambda 匿名函数,需要的数据(Data)被封装在 future 中返回。

...


int
main(int argc, char * argv[])
{
    ...

    std::printf("main BEGIN\n");

    Host host;
    future<Data> f1(host.request(30, 'A'));
    future<Data> f2(host.request(40, 'B'));
    future<Data> f3(host.request(50, 'C'));

    std::printf("main other Job BEGIN\n");
    std::this_thread::sleep_for(milliseconds(2000));
    std::printf("main other Job END\n");

    Data data1 = f1.get();
    Data data2 = f2.get();
    Data data3 = f3.get();

    std::printf("data1 = %s\n", data1.get_content().c_str());
    std::printf("data2 = %s\n", data2.get_content().c_str());
    std::printf("data3 = %s\n", data3.get_content().c_str());
    std::printf("main END\n");

    ...
}

用例向主机(Host)发送 3 个请求后,自行忙着别的事情(用等待 2 秒来模拟)后,立即要求获取请求结果(Data)。

以下类图展现了代码主要逻辑结构,

class

以下顺序图展现了线程并发中的交互。

sequence

◆ 验证测试

笔者在实验环境一中编译代码(-std=c++11)成功后运行可执行文件,

$ g++ -std=c++11 -lpthread future.cpp
$ ./a.out

运行结果如下:

...
main BEGIN
   request(30, A) BEGIN
   request(30, A) END
   request(40, B) BEGIN
   request(40, B) END
   request(50, C) BEGIN
   request(50, C) END
main other Job BEGIN
main other Job END
    (waited a while here)
data1 = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
data2 = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
data3 = CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
main END

Bye Future...

从输出过程可以看到,当用例执行完 other Job 后,虽然会主动获取结果,但仍然要等待几秒钟才会拿到 data 1~3 的内容。

◆ 相关模式

  • Future 模式可用于 Thread-Per-Message 中,当想要获取处理结果时。
  • Future 模式可用于 Worker Thread 中,当想要获取处理结果时。

◆ 最后

完整的代码请参考 [gitee] cnblogs/18842152 。更多模式请参考多线程程序设计

《Java多线程设计模式》的作者结城浩。写作中也参考了《C++并发编程实战》中的若干建议,致作者 Anthony Williams 和译者周全等。

posted @ 2025-04-25 22:04  green-cnblogs  阅读(23)  评论(0)    收藏  举报