21xrx.com
2024-12-22 20:22:45 Sunday
登录
文章检索 我的文章 写文章
C++实现手写线程池
2023-07-05 02:32:54 深夜i     --     --
C++ 线程池 手写实现

              return m_stop || !m_tasks.empty();

线程池是一个基本的多线程编程技术,它可以有效的降低多线程程序的开发和维护成本,提高程序执行效率。C++语言的线程库提供了基本的多线程支持,但是使用起来相对复杂,需要手动管理线程的创建、销毁、同步等操作。为了简化线程编程,我们可以使用C++手写线程池来实现。

线程池的核心就是一个任务队列,所有需要执行的任务都被加入到这个队列中,线程池中的所有线程共享这个任务队列。当一个线程空闲时,它会从任务队列中取出一个任务进行执行,执行完成后将结果返回,并继续取下一个任务。线程池中的线程数量可以根据实际情况进行动态调整,以保证系统的最佳性能。

下面我们来看一下如何实现一个简单的C++手写线程池:

1、定义任务类

由于线程池中的任务时异步执行的,因此需要使用一个任务类来封装需要执行的操作。这个任务类需要提供一个执行函数,用于执行具体的操作。


class Task {

public:

  Task(std::function<void()> func) : m_func(func) {}

  void operator()() {

    m_func();

  }

private:

  std::function<void()> m_func;

};

2、定义线程池类

线程池类通过一个std::queue来保存所有待执行的任务,通过std::vector来保存所有的线程。线程池类需要提供以下几个函数:

- 构造函数:初始化线程池中的线程

- 添加任务:将新的任务加入任务队列

- 停止:停止线程池中的所有线程

- 执行:启动线程池中的所有线程,不断从任务队列中取出任务进行执行


class ThreadPool {

public:

  ThreadPool(int numThreads) : m_stop(false) {

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

      m_threads.emplace_back([this] {

        for (;;) {

          Task task;

          {

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

            m_queueCond.wait(lock, [this] {

              return m_stop || !m_tasks.empty();

            });

            if (m_stop && m_tasks.empty())

              return;

            task = std::move(m_tasks.front());

            m_tasks.pop();

          }

          task();

        }

      });

    }

  }

  void Stop() {

    {

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

      m_stop = true;

    }

    m_queueCond.notify_all();

    for (std::thread& thread : m_threads)

      thread.join();

  }

  template<typename Func>

  void AddTask(Func func) {

    {

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

      m_tasks.emplace(std::make_unique<Task>(std::move(func)));

    }

    m_queueCond.notify_one();

  }

  ~ThreadPool() {

    Stop();

  }

private:

  std::vector<std::thread> m_threads;

  std::queue<std::unique_ptr<Task>> m_tasks;

  std::mutex m_queueMutex;

  std::condition_variable m_queueCond;

  bool m_stop;

};

3、使用线程池执行任务

使用线程池执行任务非常简单,只需要创建一个线程池对象,然后添加需要执行的任务即可。


ThreadPool pool(4);

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

  pool.AddTask([i] {

    std::cout << "Task " << i << " executed in thread " << std::this_thread::get_id() << std::endl;

  });

}

总结

C++手写线程池为多线程编程提供了更加方便的方式,可以大大降低代码复杂度和维护成本,提高程序执行效率。对于需要频繁使用多线程的应用程序,使用线程池是一个非常不错的选择。

  
  

评论区

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