C++ 线程池:实现、使用及注意事项
"1. 线程池是一种线程管理的机制,它包含了多个线程并行地执行任务。线程池的主要作用是减少线程的创建和销毁的开销,提高线程的复用性和执行效率。\n\n2. C++实现线程池的代码如下:\n\ncpp\n#include <iostream>\n#include <thread>\n<vector>\n<queue>\n<mutex>\n<condition_variable>\n\nclass ThreadPool {\npublic:\n ThreadPool(int numThreads) : stop(false) {\n for (int i = 0; i < numThreads; ++i) {\n workers.emplace_back([this] {\n while (true) {\n std::function<void()> task;\n \n {\n std::unique_lock<std::mutex> lock(queueMutex);\n condition.wait(lock, [this] { return stop || !tasks.empty(); });\n \n if (stop && tasks.empty()) {\n return;\n }\n \n task = std::move(tasks.front());\n tasks.pop();\n }\n \n task();\n }\n });\n }\n }\n \n template<class F>\n void enqueue(F&& task) {\n {\n std::unique_lock<std::mutex> lock(queueMutex);\n tasks.emplace(std::forward<F>(task));\n }\n \n condition.notify_one();\n }\n \n ~ThreadPool() {\n {\n std::unique_lock<std::mutex> lock(queueMutex);\n stop = true;\n }\n \n condition.notify_all();\n \n for (std::thread& worker : workers) {\n worker.join();\n }\n }\n \nprivate:\n std::vector<std::thread> workers;\n std::queue<std::function<void()>> tasks;\n \n std::mutex queueMutex;\n std::condition_variable condition;\n \n bool stop;\n};\n\nvoid taskFunc(int num) {\n std::cout << \"Task \" << num << \" is being executed.\" << std::endl;\n std::this_thread::sleep_for(std::chrono::seconds(1));\n std::cout << \"Task \" << num << \" has been executed.\" << std::endl;\n}\n\nint main() {\n ThreadPool pool(4);\n \n for (int i = 0; i < 8; ++i) {\n pool.enqueue([i] {\n taskFunc(i);\n });\n }\n \n std::this_thread::sleep_for(std::chrono::seconds(10)); // 等待所有任务执行完毕\n \n return 0;\n}\n\n\n代码解释:\n- ThreadPool 类是线程池的实现,构造函数初始化了指定数量的线程,并将它们放入 workers 容器中。\n- enqueue 函数用于向线程池中添加任务,将任务函数封装为 std::function<void()> 类型,然后加入 tasks 队列中,并通过条件变量 condition 通知线程进行任务的处理。\n- 线程函数中,通过条件变量的等待和唤醒机制,线程在有任务时执行任务,没有任务时等待。\n- 线程池的析构函数中,首先设置 stop 为真,然后通过条件变量通知所有线程停止,并等待所有线程结束。\n\n线程池的使用示例:\n在主函数中,创建一个线程池 pool,并设置线程数为 4。然后通过 enqueue 函数将 8 个任务添加到线程池中,每个任务都是调用 taskFunc 函数。最后,通过 std::this_thread::sleep_for 等待所有任务执行完毕。\n\n3. 在使用线程池时需要注意以下问题:\n- 线程池的线程数应适当,过多的线程数可能会导致系统资源耗尽,过少的线程数可能无法充分利用系统资源。\n- 线程池中的任务应该是短小的,避免长时间占用线程,阻塞其他任务的执行。\n- 线程池需要适配任务队列的大小,避免任务队列溢出。\n- 在使用线程池时,需要确保任务的线程安全性,避免多个任务对共享资源进行竞争。\n- 线程池需要适时地释放资源,避免长时间闲置的线程占用系统资源。\n\n线程池的优点:\n- 减少了线程的创建和销毁开销,提高了线程的复用性和执行效率。\n- 控制并发线程的数量,避免系统资源被过多的线程占用。\n- 能够对任务进行排队处理,避免任务的丢失和阻塞。\n\n线程池的缺点:\n- 线程池的实现较为复杂,需要考虑线程同步、任务队列、线程调度等问题。\n- 线程池的使用不适合所有场景,对于一些需要精确控制线程的场景,使用线程池会增加额外的复杂性。\n- 线程池的性能也受限于系统的硬件资源和任务的特性,不适合所有的并发应用。\n
原文地址: https://www.cveoy.top/t/topic/pBRD 著作权归作者所有。请勿转载和采集!