21xrx.com
2024-09-20 01:11:18 Friday
登录
文章检索 我的文章 写文章
C++11线程池的实现
2023-07-12 03:52:46 深夜i     --     --
C++11 线程池 实现
return this->stop || !this->tasks.empty();

随着计算机性能的提高和多核处理器的普及,多线程编程变得越来越重要。C++11引入了用于多线程编程的新特性,其中最重要的之一是std::thread类。虽然使用std::thread很容易,但在实践中,创建和销毁线程是一项开销非常大的操作。为了避免这些开销,C++11标准库还提供了std::async和std::future,可以让我们通过异步任务来利用线程。

然而,std::async只是解决了异步任务的问题,它并没有提供线程池的概念。线程池可以提高线程的利用率,因为线程的创建和销毁开销很大。使用线程池,我们可以创建一些线程,并使它们一直保持活跃状态,以便它们可以重复使用。这种方法可以大大减少线程的创建和销毁开销,从而提高程序的性能。

C++11没有提供线程池,但是我们可以使用现有的C++11特性来创建一个简单的线程池。具体来说,我们可以使用std::thread、std::function和std::queue。std::thread用于创建新线程,std::function用于绑定函数和参数,std::queue用于存储任务队列。

下面是一个简单的线程池实现:


class ThreadPool {

public:

  ThreadPool(size_t threads) {

    for (size_t i = 0; i < threads; ++i) {

      workers.emplace_back(

        [this] {

          for (;;) {

            std::function<void()> task;

            {

              std::unique_lock<std::mutex> lock(this->queue_mutex);

              this->condition.wait(lock, [this] { return this->stop || !this->tasks.empty(); });

              if (this->stop && this->tasks.empty())

                return;

              task = std::move(this->tasks.front());

              this->tasks.pop();

            }

            task();

          }

        }

      );

    }

  }

  template<class F>

  void enqueue(F&& f) {

    {

      std::unique_lock<std::mutex> lock(queue_mutex);

      tasks.emplace(std::forward<F>(f));

    }

    condition.notify_one();

  }

  ~ThreadPool() {

    {

      std::unique_lock<std::mutex> lock(queue_mutex);

      stop = true;

    }

    condition.notify_all();

    for (std::thread& worker : workers)

      worker.join();

  }

private:

  std::vector<std::thread> workers;

  std::queue<std::function<void()>> tasks;

  std::mutex queue_mutex;

  std::condition_variable condition;

  bool stop = false;

};

上面的代码实现了一个线程池,它提供了enqueue方法,将任务添加到任务队列中,并启动一个线程处理任务。在构造函数中,我们创建了指定数量的工作线程,并使用无限循环来处理任务。在enqueue方法中,我们将任务添加到队列中,然后通知等待队列的线程。

在析构函数中,我们设置stop标志,以便通知线程停止处理任务。然后,我们使用condition.notify_all()通知所有线程,然后等待线程结束。

使用线程池非常简单。我们可以创建ThreadPool对象,并使用enqueue方法添加任务到任务队列中。线程池将自动分配任务给一个可用的线程。


ThreadPool pool(4);

std::vector<std::future<void>> futures;

for (int i = 0; i < 8; ++i) {

  futures.emplace_back(

    pool.enqueue([i] {

      std::cout << "hello " << i << std::endl;

      std::this_thread::sleep_for(std::chrono::seconds(1));

      std::cout << "world " << i << std::endl;

    })

  );

}

for (auto& f : futures)

  f.get();

在上面的代码中,我们创建了一个ThreadPool对象,并将8个任务添加到任务队列中。每个任务都会打印一些文本,并在1秒后再次打印文本。使用std::future,我们可以等待所有任务完成后继续执行。

总之,线程池是一个非常有用的工具,可以显著提高多线程编程的性能。使用C++11的std::thread、std::function和std::queue,我们可以创建一个简单的线程池。该实现非常简单,可以轻松地扩展和优化,以满足不同的需求。

  
  

评论区

{{item['qq_nickname']}}
()
回复
回复