21xrx.com
2025-03-21 16:23:49 Friday
文章检索 我的文章 写文章
C++11线程池
2023-06-30 15:51:45 深夜i     --     --
C++11 线程池 多线程 并发 任务调度
return stop_ || !tasks_.empty();

C++11线程池是一种多线程的实现方式,它为开发人员提供了一种简单而高效的方式来管理并发任务。线程池允许开发人员同时执行多个任务,而不必担心线程安全和资源竞争问题。本文将介绍线程池的基本概念,以及如何使用C++11来创建线程池。

什么是线程池?

线程池本质上是一组共享线程资源的容器,其中包含了若干个线程,这些线程可以并发地处理任务。线程池为开发人员提供了一种高效的方式来管理许多小型任务,比如处理网络请求、文件读写等操作。使用线程池的最大好处是我们可以避免不必要的线程创建和销毁操作,节省了线程开销和内存开销。

如何使用C++11创建线程池?

在C++11标准中,我们可以使用std::thread头文件和std::thread类来创建线程。然而,如果我们想要创建一个线程池,需要使用std::thread头文件和std::thread类的衍生物std::future,std::packaged_task以及std::async等类和函数。

下面是一个基本的C++11线程池类:

#include <iostream>
#include <vector>
#include <queue>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <future>
#include <functional>
class ThreadPool {
public:
  ThreadPool(size_t n) {
    for (size_t i = 0; i < n; ++i) {
      workers.emplace_back([this] {
        for (;;) {
          std::function<void()> task;
          {
            std::unique_lock<std::mutex> lock(mutex_);
            cv_.wait(lock, [this] { return stop_ || !tasks_.empty(); });
            if (stop_ && tasks_.empty())
              return;
            
            task = std::move(tasks_.front());
            tasks_.pop();
          }
          task();
        }
      });
    }
  }
  template<typename F, typename... Args>
  auto enqueue(F&& f, Args&&... args)
    -> std::future<typename std::result_of<F(Args...)>::type> {
    using return_type = typename std::result_of<F(Args...)>::type;
    auto task = std::make_shared<std::packaged_task<return_type()>>(std::bind(std::forward<F>(f),std::forward<Args>(args)...));
    std::future<return_type> res = task->get_future();
    {
      std::unique_lock<std::mutex> lock(mutex_);
      if (stop_) {
        throw std::runtime_error("enqueue on stopped ThreadPool");
      }
      tasks_.emplace([task]() { (*task)(); });
    }
    cv_.notify_one();
    return res;
  }
  ~ThreadPool() {
    {
      std::unique_lock<std::mutex> lock(mutex_);
      stop_ = true;
    }
    cv_.notify_all();
    for (std::thread& worker : workers) {
      worker.join();
    }
  }
private:
  std::vector<std::thread> workers;
  std::queue<std::function<void()>> tasks_;
  std::mutex mutex_;
  std::condition_variable cv_;
  std::atomic<bool> stop_{ false };
};

上面的代码中包含了一个ThreadPool类,它的构造函数负责生成指定数量的线程,并将它们放入池子中。我们可以使用enqueue方法将我们定义的任务添加到任务队列中。

该类具有一个循环,每次从任务队列中获取任务并处理它们。通过使用std::future来返回任务的结果,我们可以确定何时它完成。

在使用C++11线程池时,我们可以将我们的代码重构为std::async函数和std::packaged_task类的结合使用。使用std::async函数时,可以指定您想要运行的函数以及该函数的参数,然后该函数将返回一个std::future类型的结果。您可以使用该值对另一个已知的线程进行分类,或者等待任务完成以提取结果。

总结

C++11线程池是一种强大而易于使用的多线程模型,可以使我们的代码更加高效和可维护。在使用线程池时,我们应该遵循一些基本的指导原则,如在确保线程安全的情况下使用互斥锁、避免不必要的内存分配和减少线程竞争等等。如果我们遵循这些最佳实践,就可以使我们的代码更加高效、可维护和健壮。

  
  

评论区