下面是一个考虑了任务优先级、异常处理和线程复用的线程池实现:
- #include <iostream>
- #include <queue>
- #include <functional>
- #include <future>
- #include <thread>
- #include <vector>
- #include <mutex>
- #include <condition_variable>
-
- enum class TaskPriority {
- Low,
- Normal,
- High
- };
-
- class ThreadPool {
- public:
- ThreadPool(size_t numThreads) : stop(false) {
- for (size_t i = 0; i < numThreads; ++i) {
- workers.emplace_back([this] {
- while (true) {
- std::function<void()> task;
-
- {
- std::unique_lock<std::mutex> lock(queueMutex);
- condition.wait(lock, [this] { return stop || !taskQueue.empty(); });
-
- if (stop && taskQueue.empty()) {
- return;
- }
-
- task = std::move(taskQueue.top().task);
- taskQueue.pop();
- }
-
- try {
- task(); // Execute the task
- } catch (const std::exception& ex) {
- std::cerr << "Exception in thread: " << std::this_thread::get_id() << ", Error: " << ex.what() << std::endl;
- }
- }
- });
- }
- }
-
- template <class F, class... Args>
- auto enqueue(TaskPriority priority, F&& f, Args&&... args) -> std::future<typename std::result_of<F(Args...)>::type> {
- using ReturnType = typename std::result_of<F(Args...)>::type;
-
- auto task = std::make_shared<std::packaged_task<ReturnType()>>(std::bind(std::forward
(f), std::forward(args)...)); - std::future<ReturnType> res = task->get_future();
-
- {
- std::unique_lock<std::mutex> lock(queueMutex);
- taskQueue.emplace(priority, [task]() { (*task)(); });
- }
-
- condition.notify_one();
-
- return res;
- }
-
- ~ThreadPool() {
- {
- std::unique_lock<std::mutex> lock(queueMutex);
- stop = true;
- }
- condition.notify_all();
- for (std::thread& worker : workers) {
- worker.join();
- }
- }
-
- private:
- struct Task {
- TaskPriority priority;
- std::function<void()> task;
-
- Task(TaskPriority p, std::function<void()> t) : priority(p), task(std::move(t)) {}
-
- // Custom comparison operator for task priority
- bool operator<(const Task& other) const {
- return priority < other.priority;
- }
- };
-
- std::vector<std::thread> workers;
- std::priority_queue<Task> taskQueue;
- std::mutex queueMutex;
- std::condition_variable condition;
- bool stop;
- };
-
- // 示例任务函数
- void printNumber(int number) {
- std::cout << "Number: " << number << ", Thread: " << std::this_thread::get_id() << std::endl;
- }
-
- int main() {
- // 创建线程池,指定线程数
- ThreadPool pool(4);
-
- // 提交任务到线程池
- for (int i = 0; i < 10; ++i) {
- auto task = [i] {
- printNumber(i);
- };
-
- if (i % 2 == 0) {
- pool.enqueue(TaskPriority::High, task);
- } else {
- pool.enqueue(TaskPriority::Normal, task);
- }
- }
-
- // 等待任务执行完成
- std::this_thread::sleep_for(std::chrono::seconds(1));
-
- return 0;
- }
在这个示例中,线程池类ThreadPool增加了以下功能:
TaskPriority枚举:用于表示任务的优先级,分为低、正常和高。Task类型:表示存储任务和优先级的数据结构。TaskPriorityComparator:用于任务优先级比较的比较器结构体。enqueue函数:在提交任务时,需要指定任务的优先级。任务被封装为std::function,并存储在任务队列中。任务执行时,会捕获并处理可能抛出的异常。在main函数中,示例代码提交了10个任务函数printNumber到线程池中进行执行。其中,奇数任务的优先级为TaskPriority::Normal,偶数任务的优先级为TaskPriority::High。最后,通过等待1秒让主线程暂停,以确保所有任务都有机会被线程池中的工作线程执行。
这个示例实现了一个更完整的线程池,考虑了任务优先级、异常处理和线程复用。每个任务都可以设置优先级,并且线程池会根据优先级来执行任务。同时,异常处理机制可以捕获任务执行过程中可能抛出的异常,以便进行相应的处理。线程复用则通过循环执行任务的方式来实现,使得线程可以重复执行多个任务,而不需要频繁地创建和销毁线程。
请注意,这只是一个简单的线程池实现示例,实际使用时可能需要根据具体需求进行更多的功能和细节处理。例如,可以添加更多的线程管理策略,如动态调整线程数量、限制最大并发数等。