线程池设计与实现

基于C++11 通用线程池

thread_pool.h

#ifndef _PTHREAD_H_
#define _PTHREAD_H_

#include <iostream>
#include <queue>
#include <vector>
#include <future>

class Pthread_Pool
{
public:
	Pthread_Pool() : m_thread_size(1), m_terminate(false) {}
	~Pthread_Pool() { thread_stop(); }

public:
	// 线程池初始化
	bool thread_init(size_t size);
	// 启动线程池各个线程
	bool thread_start();
	// 停止所有线程
	void thread_stop();
	// 任务执行入口
	template <class F, class... A>
	auto exec(F&& f, A&&... args) -> std::future<decltype(f(args...))>;

private:
	// 每个任务都是一个struct结构体,方便未来扩展
	struct Task {
		Task() {}
		std::function<void()> m_func;
	};
	// Task未来在队列中以智能指针的形式传递
	typedef std::shared_ptr<Task> task_func;

private:
	// 尝试从任务队列获取一个任务
	bool get_task(task_func& t);
	// 线程主函数
	void thread_run();

private:
	std::queue<task_func> m_tasks;  // 任务队列
	std::vector<std::thread*> m_threads;  // 线程池
	std::mutex m_mutex;  //锁
	std::condition_variable m_cond;  // 用于线程之间通知的条件变量
	size_t m_thread_size;  // 线程池大小
	bool m_terminate;  // 标记线程是否结束
	std::atomic<int> m_atomic{0};  // 用于记录状态的原子变量
};

#endif _PTHREAD_H_

thread_pool.cpp

#include "pthread_pool.h"

// 线程池初始化
bool Pthread_Pool::thread_init(size_t size) {
	std::unique_lock<std::mutex> lock(m_mutex);
	if (!m_threads.empty()) {
		return false;
	}
	m_thread_size = size;
}

// 启动线程池各个线程
bool Pthread_Pool::thread_start() {
	std::unique_lock<std::mutex> lock(m_mutex);
	if (!m_threads.empty()) {
		return false;
	}
	for (size_t i = 0; i < m_thread_size; i++) {
		m_threads.emplace_back(new std::thread(&Pthread_Pool::thread_run, this));
	}
	return true;
}

// 停止所有线程
void Pthread_Pool::thread_stop() {
	{
		std::unique_lock<std::mutex> lock(m_mutex);
		m_terminate = true;
		m_cond.notify_all();
	}

	for (auto& m_thread : m_threads) {
		if (m_thread->joinable()) {
			m_thread->join();
		}
		delete m_thread;
		m_thread = nullptr;
	}

	std::unique_lock<std::mutex> lock(m_mutex);
	m_threads.clear();
}

// 线程主函数
void Pthread_Pool::thread_run() {
	while (!m_terminate) {
		task_func task;
		bool ok = get_task(task);
		if (ok) {
			++m_atomic;
			task->m_func();
			--m_atomic;

			std::unique_lock<std::mutex> lock(m_mutex);
			if (m_atomic == 0 && m_tasks.empty()) { // 是否所有任务都执行完成
				m_cond.notify_all();
			}
		}
	}
}

// 尝试从任务队列获取一个任务
bool Pthread_Pool::get_task(task_func& t) {
	std::unique_lock<std::mutex> lock(m_mutex);
	if (m_tasks.empty()) {
		m_cond.wait(lock, [this] {return m_terminate || !m_tasks.empty(); });
	}

	if (m_terminate) return false;

	t = std::move(m_tasks.front());
	m_tasks.pop();
	return true;
}

// 任务执行入口
template <class F, class... A>
auto Pthread_Pool::exec(F&& f, A&&... args) -> std::future<decltype(f(args...))> {
	using retType = decltype(f(args...));
	auto task = std::make_shared<std::packaged_task<retType>>(bind(std::forward<F>(f), std::forward<A>(args)...));
	task_func f_ptr = std::make_shared<task>();
	f_ptr->m_func = [task]() { (*task)(); };

	std::unique_lock<std::mutex> lock(m_mutex);
	m_tasks.push(f_ptr);
	m_cond.notify_one();

	return task->get_future();
}

main.cpp

#include "pthread_pool.h"
#include <iostream>
using namespace std;

void threadFunc(int a) {
    cout << "a=" << a << endl;
}

class A {
public:
    A() = default;
    int run(int a, int b) {
        return a + b;
    }
};

int main() {
    Pthread_Pool p1;
    p1.thread_init(10);
    p1.thread_start();
    p1.exec(threadFunc, 100);
    p1.exec(threadFunc, 200);

    A a1;
    auto fu1 = p1.exec(std::bind(&A::run, &a1, std::placeholders::_1, std::placeholders::_2), 10, 20);
    int ret = fu1.get();
    std::cout << "res:" << ret << std::endl;

    p1.thread_stop();
    return 0;
}
posted @ 2023-10-14 09:18  洋綮  阅读(15)  评论(0)    收藏  举报