线程池的实现V2.0

55 阅读2分钟

说明

该版本添加了停止线程池的方法,使用了智能指针,并且可以异步获取返回值

线程池类头文件

x_thread_pool.h

#pragma once
#include <thread>
#include <mutex>
#include <vector>
#include <list>
#include <functional>
#include <atomic>
#include <future>

class XTask
{
public:
	virtual int Run() = 0;  // 任务的入口函数
	std::function<bool()> is_exit = nullptr;

	auto GetReturn()
	{
		// 阻塞等待
		return p_.get_future().get();
	}

	void SetValue(int v)
	{
		p_.set_value(v);
	}
private:
	// 用来接收返回值
	std::promise<int> p_;
};

class XThreadPool
{
public:
	// 初始化线程池
	// num 为线程的数量
	void Init(int num);

	// 启动所有线程,调用前必须先调用Init
	void Start();

	// 线程池退出
	void Stop();

	// 插入任务
	void AddTask(std::shared_ptr<XTask> task);

	// 获取任务
	std::shared_ptr<XTask> GetTask();

	// 线程池是否退出
	bool is_exit()
	{
		return is_exit_;
	}

	int task_run_count()
	{
		return task_run_count_;
	}

private:
	// 线程池线程的入口函数
	void Run();
	int thread_num_ = 0;  // 线程数量
	std::mutex mux_;
	std::vector<std::shared_ptr<std::thread>> threads_;
	std::list<std::shared_ptr<XTask>> tasks_;
	std::condition_variable cv_;
	bool is_exit_ = false; // 线程池退出

	std::atomic<int> task_run_count_ = {0};  // 正在运行的函数数量
};


实现文件

x_thread_pool.cpp

#include "x_thread_pool.h"
#include <iostream>

using namespace std;

void XThreadPool::Init(int num)
{
	unique_lock<mutex> lock(mux_);
	this->thread_num_ = num;

	cout << "Thread pool init " << num << "\n";
}

// 启动所有线程,必须先调用Init

void XThreadPool::Start()
{
	unique_lock<mutex> lock(mux_);

	if (thread_num_ <= 0)
	{
		cerr << "Please Init XThreadPool" << "\n";
	}

	if (!threads_.empty())
	{
		cerr << "Thread pool has start!" << "\n";
	}

	// 启动线程
	for (int i = 0; i < thread_num_; i++)
	{
		auto th = make_shared<thread>(&XThreadPool::Run, this);
		threads_.push_back(th);
	}


}

void XThreadPool::Stop()
{
	is_exit_ = true;
	cv_.notify_all();

	for (auto& th: threads_)
	{
		th->join();
	}

	unique_lock<mutex> lock(mux_);
	threads_.clear();

}


void XThreadPool::Run()
{
	cout << "begin XThreadPool Run" << this_thread::get_id() << '\n';

	while(!is_exit())
	{
		auto task = GetTask();
		++task_run_count_;  // 运行一个任务时候数量加1
		if (!task) continue;
		try
		{
			auto re = task->Run();
			task->SetValue(re);
		} catch (...)
		{
			
		}
		--task_run_count_;
	}

	cout << "exit XThreadPool Run" << this_thread::get_id() << '\n';


}

void XThreadPool::AddTask(std::shared_ptr<XTask> task)
{
	unique_lock<mutex> lock(mux_);
	tasks_.push_back(task);

	task->is_exit = [this]
		{
			return is_exit();
		};

	lock.unlock();
	cv_.notify_one();

}

std::shared_ptr<XTask> XThreadPool::GetTask()
{
	unique_lock<mutex> lock(mux_);

	if (tasks_.empty())
	{
		cv_.wait(lock);

	}

	if (is_exit()) return nullptr;

	if (tasks_.empty())
	{
		return nullptr;
	}

	auto task = tasks_.front();

	tasks_.pop_front();
	return task;

}

入口文件


#include <iostream>
#include "x_thread_pool.h"

using namespace std;

class MyTask:public XTask
{
public:
    int Run() override
    {
	    std::cout << "MyTask" << name << '\n';
        for (int i = 0; i < 10; i++)
        {
            if (is_exit()) break;
            cout << "." << flush;
            this_thread::sleep_for(500ms);
        }
        return 111;
    }

    std::string name = "";
};

int main()
{

    XThreadPool pool;
    pool.Init(16);
    pool.Start();

    auto task1 = make_shared<MyTask>();
    task1->name = "test name 001";


    pool.AddTask(task1);

    auto re = task1->GetReturn();

    cout << "task1 return: " << re << '\n';  // 等待运行结束获取返回结果

    this_thread::sleep_for(1s);
    pool.Stop();

    getchar();

    return 0;

}