@@ -425,22 +425,22 @@ int print_task2(int n) {
425425}
426426
427427int main() {
428- ThreadPool pool{ 4 }; // 创建一个有 4 个线程的线程池
428+ ThreadPool pool{ 4 }; // 创建一个有 4 个线程的线程池 构造函数自动启动线程池
429429 std::vector< std::future<int > > futures; // future 集合,获取返回值
430430
431431 for (int i = 0; i < 10; ++i) {
432432 futures.emplace_back(pool.submit(print_task, i));
433433 }
434- pool.join();
434+ pool.join(); // 阻塞,让任务全部执行完毕
435435
436436 std::puts("---------------------");
437437
438- pool.start();
438+ pool.start(); // 重新启动线程池
439439
440440 for (int i = 0; i < 10; ++i) {
441441 futures.emplace_back(pool.submit(print_task2, i));
442442 }
443- pool.join();
443+ pool.join(); // 阻塞,让任务全部执行完毕
444444
445445 int sum = 0;
446446 for(auto& future : futures){
@@ -477,7 +477,31 @@ Task 1 is running.
477477sum: 90
478478```
479479
480- > 如果不自己显式调用 ` join() ` ,而是等待线程池对象调用析构函数,那么效果如同 ` asio::thread_pool ` ,会先进行 ` stop ` ,导致一些任务不执行。
480+ > 如果不自己显式调用 ` join() ` ,而是等待线程池对象调用析构函数,那么效果如同 ` asio::thread_pool ` ,会先进行 ` stop ` ,导致一些任务无法执行。
481+
482+ 它支持** 任意可调用类型** ,当然也包括非静态成员函数。我们使用了 [ ` std::decay_t ` ] ( https://zh.cppreference.com/w/cpp/types/decay ) ,所以参数的传递其实是** 按值复制** ,而不是引用传递,这一点和大部分库的设计一致。示例如下:
483+
484+ ``` cpp
485+ struct X {
486+ void f(const int& n)const{
487+ std::cout << &n << '\n';
488+ }
489+ };
490+
491+ X x;
492+ int n = 6 ;
493+ std::cout << &n << ' \n ' ;
494+ pool.start();
495+ pool.submit(&X::f, &x, n); // 默认复制,地址不同
496+ pool.submit(&X::f, &x, std::ref(n));
497+ pool.join();
498+ ```
499+
500+ > [ 运行] ( https://godbolt.org/z/vTc7M8Kov ) 测试。
501+
502+ 我们的线程池的 ` submit ` 成员函数在传递参数的行为上,与先前介绍的 ` std::thread ` 和 ` std::async ` 等设施基本一致。
503+
504+ 我们稍微介绍线程池的接口:
481505
482506 ** 构造函数和析构函数:**
483507
0 commit comments