接上篇 c++标准库:并发(一) —— 高级接口 async()和futrue
thread相关的api可以通过#include <thread>
来引入,promise相关的api在#include <future>
中。
std::thread 的 join和detach
- 和
std::async
方式启动异步任务不同,std::thread会无条件的在一个独立线程中启动任务并开始执行
如果希望当前线程等待知道线程t执行结束,那就调用t.join()
- 如果打算将线程t从母体卸离,使它运行于后台而不受任何控制,那就调用t.detach()
- 如果线程t的生命周期结束,或者发生了一次Move Assignment时仍未调用join或者detach,程序将终止并调用std::terminal()
- 进程结束时所有detach的线程奖杯强制结束
1 2 3 4 5 6 7 8
|
void TestJoin(){ std::thread t1(doSomething, '+'); std::thread t2(doSomething, '-'); t1.join(); t2.join(); }
|
1 2 3 4 5 6 7 8 9
| void TestDetach(){ std::thread t1(doSomething, '+'); std::thread t2(doSomething, '-'); t1.detach(); t2.detach(); std::this_thread::sleep_for(std::chrono::milliseconds(500)); std::cout << "job done!" << std::endl; }
|
std::promise 持有结果和异常
可以在线程中通过 promise.set_value
和 promise. set_exception
来为promise对象设置结果或者异常。
在线程任务执行结束后,主线程从promise对象get一个future对象,并通过调用future.get()来获取promise持有的结果中获取最终结果或者抛出异常。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| void doSomethingPromise(std::promise<std::string> &p){ try{ std::srand(324312); int rand = std::rand() % 100; std::cout << "current thread:" << std::this_thread::get_id() << std::endl; if(rand>50){ p.set_value("promise resolve!" + std::to_string(rand)); } else { throw std::runtime_error("promise reject " + std::to_string(rand)); } } catch(...){ p.set_exception(std::current_exception()); } }
// Promise,可以resolve、reject // Promise不仅可以用在多线程场景中,也可以用来在单线程场景持有一个结果或者异常,放后面处理 void TestPromise(){ std::promise<std::string> p; // 注意这里传递promsie的引用进去,要用std::ref(p),而不能 &p std::thread t(doSomethingPromise, std::ref(p)); t.detach(); std::future<std::string> f = p.get_future(); try{ std::cout << f.get() << std::endl; } catch(std::exception &e){ std::cout << e.what() << std::endl; } }
|
std::packaged_task 打包任务
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| double compute(int a, int b){ std::cout << " in thread " << std::this_thread::get_id() << std::endl; std::this_thread::sleep_for(std::chrono::seconds(a+b)); return a+b; }
void TestPackagedTask(){ std::packaged_task<double(int, int)> pt(compute), pt2(compute); std::future<double> f = pt.get_future(), f2 = pt2.get_future(); std::cout << " start packaged task " << std::endl; std::thread t1([&]{pt(1, 4);}); std::thread t2([&]{pt2(1, 4);}); t1.detach(); t2.detach(); std::cout << " packaged task result: " << f.get() << " result2:" << f2.get() << std::endl; }
|
本文链接:https://www.zoucz.com/blog/2021/06/09/91711c10-c875-11eb-9fe7-534bbf9f369d/