在C++11之前,我们要在程序中新建一个线程是很麻烦的,不过好在现在借助C++11和boost库,我们可以非常方便的以各种姿势往程序里新加几个线程了。本文为你总结了以下3种方式来新建线程:

  • std::thread:c++11提供的线程类,使用它可以很容易的新建和运行一个线程
  • std::async:c++11提供的创建任务的方法,是比std::thread更加高一层的工具,用它既可以创建线程,也能让标准库“智能”的帮你判断是否是新建一个线程还是延迟处
  • boost::asio::thread_pool:通常在需要创建大量线程的时候,使用线程池可以避免线程的重复创建。可惜c++11没有现成的方法创建线程池,我们可以借助boost库来实现。

    std::thread

    ```cpp

    include

    include

    include

    include

std::string GetThreadIdString(const std::thread::id& id) { std::stringstream ss; ss << id; return ss.str(); }

int Mytask(int iNum) { // 这里不使用”cout << A << B << C”而使用”cout << A + B + C”,因为前者是3个cout的步骤,多线程下容易输出混乱,而后者只有一个cout步骤 std::cout << “tid(“+ GetThreadIdString(std::this_thread::get_id()) +”) “ + “do:” + std::to_string(iNum) + “\n”; return iNum; }

//演示std::promise void MyTask2(int iNum, std::promise& pr) { int iRet = Mytask(iNum); pr.set_value_at_thread_exit(iRet); //在线程中对std::promise中的future赋值 }

int main(int argc, char *argv[]) { std::promise pr1; std::promise pr2; std::promise pr3; std::promise xxpr4; std::promise pr5; std::packaged_task task6(Mytask);

  1. std::thread t1(MyTask2, 1, std::ref(pr1));
  2. std::thread t2(MyTask2, 2, std::ref(pr2));
  3. std::thread t3(MyTask2, 3, std::ref(pr3));
  4. std::thread t4(MyTask2, 4, std::ref(pr4));
  5. std::thread t5(MyTask2, 5, std::ref(pr5));
  6. std::thread t6(std::ref(task6), 6);
  7. //t.join(); //阻塞线程池,避免main函数结束导致线程中的任务没运行
  8. std::this_thread::sleep_for(std::chrono::milliseconds(1000)); //阻塞main函数线程1s,给时间让线程池中的任务运行
  9. std::cout << "rst1:" << pr1.get_future().get() << std::endl;
  10. std::cout << "rst2:" << pr2.get_future().get() << std::endl;
  11. std::cout << "rst3:" << pr3.get_future().get() << std::endl;
  12. std::cout << "rst4:" << pr4.get_future().get() << std::endl;
  13. std::cout << "rst5:" << pr5.get_future().get() << std::endl;
  14. std::cout << "rst6:" << task6.get_future().get() << std::endl;
  15. t1.join();
  16. t2.join();
  17. t3.join();
  18. t4.join();
  19. t5.join();
  20. t6.join();

}

  1. 运行结果:<br />![image.png](https://cdn.nlark.com/yuque/0/2022/png/675577/1649152764417-c4c96dda-316d-4639-8ded-33ffceecb099.png#clientId=u679589ee-d091-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=252&id=u2c0ac452&margin=%5Bobject%20Object%5D&name=image.png&originHeight=504&originWidth=1436&originalType=binary&ratio=1&rotation=0&showTitle=false&size=71388&status=done&style=none&taskId=udf6cfaa5-c87b-4113-aefc-0f42ffc4619&title=&width=718)
  2. <a name="oKJXy"></a>
  3. ## std::async
  4. ```cpp
  5. #include <iostream>
  6. #include <thread>
  7. #include <future>
  8. #include <sstream>
  9. std::string GetThreadIdString(const std::thread::id& id)
  10. {
  11. std::stringstream ss;
  12. ss << id;
  13. return ss.str();
  14. }
  15. int Mytask(int iNum)
  16. {
  17. // 这里不使用"cout << A << B << C"而使用"cout << A + B + C",因为前者是3个cout的步骤,多线程下容易输出混乱,而后者只有一个cout步骤
  18. std::cout << "tid("+ GetThreadIdString(std::this_thread::get_id()) +") " + "do:" + std::to_string(iNum) + "\n";
  19. return iNum;
  20. }
  21. int main(int argc, char *argv[]) {
  22. std::future<int> fut1 = std::async(std::launch::async, Mytask, 1);
  23. std::future<int> fut2 = std::async(std::launch::async, Mytask, 2);
  24. std::future<int> fut3 = std::async(std::launch::async, Mytask, 3);
  25. std::future<int> fut4 = std::async(std::launch::async, Mytask, 4);
  26. std::future<int> fut5 = std::async(std::launch::async, Mytask, 5);
  27. std::future<int> fut6 = std::async(std::launch::async, Mytask, 6);
  28. std::this_thread::sleep_for(std::chrono::milliseconds(1000)); //阻塞main函数线程1s,给时间让线程池中的任务运行
  29. std::cout << "rst1:" << fut1.get() << std::endl;
  30. std::cout << "rst2:" << fut2.get() << std::endl;
  31. std::cout << "rst3:" << fut3.get() << std::endl;
  32. std::cout << "rst4:" << fut4.get() << std::endl;
  33. std::cout << "rst5:" << fut5.get() << std::endl;
  34. std::cout << "rst6:" << fut6.get() << std::endl;
  35. }

运行结果:
image.png

boost::asio::thread_pool

  1. #include <iostream>
  2. #include <boost/asio.hpp>
  3. #include <boost/asio/thread_pool.hpp>
  4. #include <thread>
  5. #include <sstream>
  6. std::string GetThreadIdString(const std::thread::id& id)
  7. {
  8. std::stringstream ss;
  9. ss << id;
  10. return ss.str();
  11. }
  12. int MyTask(int iNum)
  13. {
  14. // 这里不使用"cout << A << B << C"而使用"cout << A + B + C",因为前者是3个cout的步骤,多线程下容易输出混乱,而后者只有一个cout步骤
  15. std::cout << "tid("+ GetThreadIdString(std::this_thread::get_id()) +") " + "do:" + std::to_string(iNum) + "\n";
  16. return iNum;
  17. }
  18. int main(int argc, char *argv[]) {
  19. boost::asio::thread_pool pool(4); //4线程的线程池
  20. //陆续将任务塞入线程池
  21. boost::asio::post(pool, std::bind(MyTask, 1));
  22. boost::asio::post(pool, std::bind(MyTask, 2));
  23. boost::asio::post(pool, std::bind(MyTask, 3));
  24. boost::asio::post(pool, std::bind(MyTask, 4));
  25. boost::asio::post(pool, std::bind(MyTask, 5));
  26. boost::asio::post(pool, std::bind(MyTask, 6));
  27. boost::asio::post(pool, std::bind(MyTask, 7));
  28. boost::asio::post(pool, std::bind(MyTask, 8));
  29. boost::asio::post(pool, std::bind(MyTask, 9));
  30. boost::asio::post(pool, std::bind(MyTask, 10));
  31. //pool.join(); //阻塞线程池,避免main函数结束导致线程中的任务没运行
  32. std::this_thread::sleep_for(std::chrono::milliseconds(1000)); //阻塞main函数线程1s,给时间让线程池中的任务运行
  33. pool.join();
  34. }

运行结果:
image.png