C++11 std::thread 实现
std::thread主要接口thread() noexcept; // 创建不表示线程的空线程对象 template class Function, class... Args explicit thread( Function f, Args... args ); // 创建新线程并执行函数 thread( const thread ) delete; // 不可复制构造 thread( thread other ) noexcept; // 移动构造 join() //阻塞当前线程直到目标线程执行完毕 detach() //分离线程允许线程独立执行;分离后线程对象不再管理该线程 joinable() //检查线程是否可合并 //返回 true 的情况 //1.通过构造函数创建且未调用 join/detach //2.已移动但未管理的线程对象 get_id() //返回线程的唯一标识符,如果线程不可合并返回默认构造的 id hardware_concurrency() //返回硬件支持的并发线程数,用于指导线程池大小设置 void swap(thread _Other) noexcept//交换两个 std::thread 对象的底层句柄-实例#include stdio.h // 标准输入输出头文件 #include stdlib.h // 标准库头文件包含exit等函数 #include iostream // C标准输入输出流 #include cstring #include thread #include chrono using namespace std; // 使用std命名空间 // 线程函数 - 子线程的入口点 void PrintThread(int param) { thread::id thread_id this_thread::get_id(); cout ChildThread: id thread_id endl; // 这里打印的是进程ID for (int i 0; i 100; i) { cout i endl; this_thread::sleep_for(chrono::seconds(1)); // 休眠1秒模拟耗时操作 } } //静态函数 static void staticPrintThread(int param){ return PrintThread(param); } int main(int argc, char* argv[]) { thread::id main_id this_thread::get_id(); // 获取当前进程ID cout main Self: id main_id endl; int temp 50; // 创建新线程 thread t(PrintThread,temp); //thread t(staticPrintThread,temp); //引用传递 //thread t(PrintThread,ref(temp); // 主线程继续执行自己的工作与子线程并发执行 for (int i 0; i 5; i) { cout Main thread i endl; // 主线程输出 this_thread::sleep_for(chrono::seconds(2)); // 休眠2秒子线程休眠1秒所以子线程输出更频繁 } if (t.joinable()) { t.join(); } return 0; }Lambda表达式int temp 5; thread t([temp](int count){ for (int i temp; i count; i) { cout i endl; this_thread::sleep_for(chrono::seconds(1)); // 休眠1秒模拟耗时操作 } },30);调用类普通方法、类静态方法#include iostream #include thread #include chrono #include functional using namespace std; class ProgramA{ public: void PrintThread(){ thread::id thread_id this_thread::get_id(); cout thread_id: thread_idendl; for(int i 0;i50;i){ coutfun i endl; this_thread::sleep_for(chrono::seconds(1)); } return; }; static void staticPrintThread(){ thread::id thread_id this_thread::get_id(); cout thread_id: thread_idendl; for(int i 0;i50;i){ coutstatic i endl; this_thread::sleep_for(chrono::seconds(1)); } return ; } }; int main(){ thread t1(ProgramA::staticPrintThread); ProgramA PA; thread t2(ProgramA::PrintThread,PA); thread t3(bind(ProgramA::PrintThread,PA)); thread t4(ProgramA::PrintThread,PA); t1.join(); t2.join(); t3.join(); t4.join(); }promise、future、async问题如果有一个使用场景计算A需要5min计算B需要4分钟执行C动作需要完成A和B。不使用多线程时需要9min才能执行C使用多线程时只需要5min就可以完成前面步骤。但是如何保证AB完成后才让C执行。在执行C之前让A、B join();使用promise、future、asyncpromise-future 对是通过共享状态来帮助线程间传递值或异常的一种沟通通道。是实现线程同步的一种方式。std::promise数据提供者用于存储一个值或异常之后可以通过与之关联的std::future来获取这个值或异常。std::future数据接收者提供一个异步操作结果的访问。它可以等待阻塞直到std::promise设置好值然后获取该值。std::async用于异步执行任务并返回一个std::future对象来获取结果promise、future示例promiseget_future(): 返回一个与该promise关联的future对象。每个 promise 只能调用一次get_future()多次调用会抛出std::future_error异常。set_value(value): 设置异步操作的结果值。如果多次调用会抛出std::future_error异常。set_exception(exception_ptr): 设置异步操作的异常。set_value_at_thread_exit(value): 设置异步操作的结果值但该值会在当前线程退出时才变得可用。set_exception_at_thread_exit(exception_ptr): 设置异步操作的异常但该异常会在当前线程退出时才变得可用。futureget(): 阻塞当前线程直到异步操作完成并返回结果。get()只能调用一次第二次调用会抛出std::future_error异常。wait(): 阻塞当前线程直到异步操作完成但不获取结果。wait_for(duration): 阻塞当前线程直到异步操作完成或指定的时间已过。wait_until(time_point): 阻塞当前线程直到异步操作完成或到达指定的时间点。设置返回值1 #include iostream 2 #include thread 3 #include chrono 4 #include functional 5 #include future 6 7 using namespace std; 8 void computeA(promiseint prom){ 9 this_thread::sleep_for(chrono::seconds(5));//5s 10 cout A执行完成! 5s endl; 11 prom.set_value(1);//设置结果值 12 } 13 14 15 void computeB(promisefloat prom){ 16 this_thread::sleep_for(chrono::seconds(4));//4s 17 cout B执行完成! 4s endl; 18 prom.set_value(1);//设置结果值 19 } 20 21 22 void computeC(futureint futi,futurefloat futf){ 23 cout C开始 endl; 24 futi.get(); 25 futf.get(); 26 cout C接受A B结果后执行! endl; 27 } 28 29 int main(){ 30 31 promiseint prom_i; 32 futureint resultFutI prom_i.get_future(); 33 34 promisefloat prom_f; 35 futurefloat resultFutF prom_f.get_future(); 36 37 38 thread threadA thread(computeA , move(prom_i)); 39 40 thread threadB thread(computeB , move(prom_f)); 41 42 thread threadC thread(computeC , move(resultFutI) , move(resultFutF)); 43 44 45 threadA.join(); 46 47 threadB.join(); 48 49 threadC.join(); 50 }设置异常1 #include iostream 2 #include thread 3 #include chrono 4 #include functional 5 #include future 6 using namespace std; 7 void funAThrowException(std::promiseint prom) { 8 try { 9 throw std::runtime_error(An error occurred); 10 } catch (...) { 11 prom.set_exception(std::current_exception()); 12 } 13 } 14 15 void funBReceiveException(std::futureint fut) { 16 try { 17 int value fut.get(); 18 } catch (const std::exception e) { 19 std::cout Caught exception: e.what() std::endl; 20 } 21 } 22 23 24 int main(){ 25 coutmain fun! endl; 26 promiseint prom; 27 futureint fut prom.get_future(); 28 thread threadA thread(funAThrowException,move(prom)); 29 thread threadB thread(funBReceiveException,move(fut)); 30 threadA.join(); 31 threadB.join(); 32 return 0; 33 34 }