@@ -425,22 +425,22 @@ int print_task2(int n) {
425
425
}
426
426
427
427
int main() {
428
- ThreadPool pool{ 4 }; // 创建一个有 4 个线程的线程池
428
+ ThreadPool pool{ 4 }; // 创建一个有 4 个线程的线程池 构造函数自动启动线程池
429
429
std::vector< std::future<int > > futures; // future 集合,获取返回值
430
430
431
431
for (int i = 0; i < 10; ++i) {
432
432
futures.emplace_back(pool.submit(print_task, i));
433
433
}
434
- pool.join();
434
+ pool.join(); // 阻塞,让任务全部执行完毕
435
435
436
436
std::puts("---------------------");
437
437
438
- pool.start();
438
+ pool.start(); // 重新启动线程池
439
439
440
440
for (int i = 0; i < 10; ++i) {
441
441
futures.emplace_back(pool.submit(print_task2, i));
442
442
}
443
- pool.join();
443
+ pool.join(); // 阻塞,让任务全部执行完毕
444
444
445
445
int sum = 0;
446
446
for(auto& future : futures){
@@ -477,7 +477,31 @@ Task 1 is running.
477
477
sum: 90
478
478
```
479
479
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
+ 我们稍微介绍线程池的接口:
481
505
482
506
** 构造函数和析构函数:**
483
507
0 commit comments