多线程程序设计(七)——Thread-Per-Message
本文摘要了《Java多线程设计模式》一书中提及的 Thread-Per-Message 模式的适用场景,并针对书中例子(若干名称有微调)给出一份 C++ 参考实现及其 UML 逻辑图,也列出与之相关的模式。
◆ 适用场景
当前线程将某个函数调用委托给其它线程去完成,自己可以继续后面的处理,而无需等待被委托的函数先完成。
◆ 解决方案
将委托的函数调用转变为创建 std::thread(1)或 std::async(2)的请求,相应地会启动一条独立的线程用以处理该请求。
◆ 参考实现
例子模拟了主程序向某台主机(Host)发送打印文本请求的过程。Host 会启动一个独立的线程,使用 Helper 类进行实际的打印文本的工作。
class Helper
{
  public:
    void
    handle(int count, char c)
    {
        std::printf("   handle(%d, %c) BEGIN\n", count, c);
        for (int i = 0; i < count; ++i) {
            std::this_thread::sleep_for(milliseconds(100));
            std::printf("%c", c);
        }
        std::printf("   handle(%d, %c) END\n", count, c);
    }
};
class Host
{
    ...
    Helper
    __helper__;
    ...
    thread
    request(int count, char c)                                  #1
    {
        std::printf("   request(%d, %c) BEGIN\n", count, c);
        thread t([this, count, c] {
            __helper__.handle(count, c);
        });
        std::printf("   request(%d, %c) END\n", count, c);
        return t;
    }
    future<void> request(int count, char c)                     #2
    {
        std::printf("   request(%d, %c) BEGIN\n", count, c);
        future<void> f = std::async(launch::async, [=] {
                                        __helper__.handle(count, c);
                                    });
        std::printf("   request(%d, %c) END\n", count, c);
        return f;
    }
};
Host 响应请求的方式有两种,分为直接启动 std::thread(#1)对象或使用 std::async(#2)在分离的线程执行任务。
以下类图展现了代码主要逻辑结构,

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

◆ 验证测试
笔者在实验环境一中编译代码(-std=c++11)成功后运行可执行文件,
$ g++ -std=c++11 -lpthread thread-per-message.cpp
$ ./a.out
运行结果如下:
...
main BEGIN
   request(30, A) BEGIN
   request(30, A) END
   request(40, B) BEGIN
   handle(30, A) BEGIN
   request(40, B) END
   request(50, C) BEGIN
   handle(40, B) BEGIN
   request(50, C) END
main END
   handle(50, C) BEGIN
ABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCABCA   handle(30, A) END
BCBCBCBCBCBCBCBCBCBCB   handle(40, B) END
CCCCCCCCCCC   handle(50, C) END
Bye Thread-Per-Message...
...
可以看到主线程的任务先完成后分离的线程才陆续完成打印请求。
◆ 相关模式
- 如果想利用有限的线程资源,可以使用 Worker Thread 模式。
 - 如果想要获取处理的结果,可以使用 Future 模式。
 
◆ 最后
完整的代码请参考 [gitee] cnblogs/18818610 。更多模式请参考多线程程序设计。
致《Java多线程设计模式》的作者结城浩。写作中也参考了《C++并发编程实战》中的若干建议,致作者 Anthony Williams 和译者周全等。
受限于作者的水平,读者如发现有任何错误或有疑问之处,请追加评论或发邮件联系 green-pi@qq.com。作者将在收到意见后的第一时间里予以回复。 本文来自博客园,作者:green-cnblogs,转载请注明原文链接:https://www.cnblogs.com/green-cnblogs/p/18818610 谢谢!
                    
                
                
            
        
浙公网安备 33010602011771号