c++11:跨平台线程池

跨平台线程池实现

它使用 C++11 标准库中的 std::thread、std::mutex、std::condition_variable、std::function 和 std::queue 等组件实现。

代码实现

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <queue>

class ThreadPool {
public:
	ThreadPool(int numThreads) : stop(false)
	 {
		for (int i = 0; i < numThreads; ++i) 
		{
		//这里传入一个匿名函数。这个匿名函数会作为线程的入口函数
		//内部的实现为thread t(匿名函数)
		//因为emplace_back(),只需要传入构造函数所需要的参数就行了,它会在内部构造一个线程thread
		//因为传入的参数是一个匿名函数,所以这个匿名函数就会作为线程的入口函数
			threads.emplace_back([this]
			 {
				while (true)
				 {
					std::unique_lock<std::mutex> lock(mutex);
					condition.wait(lock, [this] { return stop || !tasks.empty(); });
					if (stop && tasks.empty()) {
						return;
					}
					std::function<void()> task(std::move(tasks.front()));//从任务池里面取出任务
					tasks.pop();//任务池任务减少
					lock.unlock();//解锁
					task();//执行任务
				}
			});
		}
	}

	~ThreadPool() {
		{
			std::unique_lock<std::mutex> lock(mutex);
			stop = true;
		}
		condition.notify_all();
		for (std::thread& thread : threads) {
			thread.join();
		}
	}
//可变参数模版,调用时参数个数可以变化
	template<typename F, typename... Args>
	void enqueue(F&& f, Args&&... args) 
	{
	//使用完美转发将可变参数传给对应的执行任务的函数task()
		std::function<void()> task(std::bind(std::forward<F>(f), std::forward<Args>(args)...));
		{
			std::unique_lock<std::mutex> lock(mutex);
			tasks.emplace(std::move(task));//添加任务
		}
		condition.notify_one();//唤醒线程
	}

private:
	std::vector<std::thread> threads;
	std::queue<std::function<void()>> tasks;
	std::mutex mutex;
	std::condition_variable condition;
	bool stop;
};

int main() {
	ThreadPool pool(4);
	for (int i = 0; i < 8; ++i) {
		pool.enqueue([i] {
			std::cout << "Task " << i << " is running in thread " << std::this_thread::get_id() << std::endl;
			std::this_thread::sleep_for(std::chrono::seconds(1));
			std::cout << "Task " << i << " is done" << std::endl;
		});
	}
	return 0;
}

Task Task 1 is running in thread 0 is running in thread 4492 Task 2 is
running in thread 1348 11900 Task 3 is running in thread 13280 Task
Task 1Task is done2 is doneTask Task 340 is running in thread is
done4492

Task is done5 is running in thread 1348 Task 6Task is running in
thread 713280 is running in thread 11900 Task Task 7Task is doneTask
45 is done is done

6 is done

代码变形

使用函数指针

使用函数指针作为线程的入口参数;

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <functional>
#include <queue>
//使用模版函数 这里如果写ThreadPool*的话,会编译不过,因为ThreadPool类的声明在后面
template<typename T>
void threadAdapter(T pool)
{
	pool->threadExec();
}

class ThreadPool
{
public:

	ThreadPool(int numThreads) : stop(false)
	{
		for (int i = 0; i < numThreads; ++i)
		{
		//这里使用类外的函数,如果是类的成员函数需要使用静态成员函数,非静态成员函数要指明调用对象。
			void(*fun)(ThreadPool*) = &threadAdapter;
			std::thread t(fun,this);//创建一个线程
			threads.push_back(std::move(t));//将线程入队
		}
	}
	 void threadExec()
	{
		while (true)
		{
			std::unique_lock<std::mutex> lock(mutex);
			condition.wait(lock, [this]() { return stop || !tasks.empty(); });
			if (stop && tasks.empty())
			{
				return;
			}
			std::function<void()> task(std::move(tasks.front()));
			tasks.pop();
			lock.unlock();
			task();
		}
	}
	~ThreadPool()
	{
		{
			std::unique_lock<std::mutex> lock(mutex);
			stop = true;
		}
		condition.notify_all();
		for (std::thread& thread : threads)
		{
			thread.join();
		}
	}

	template<typename F, typename... Args>
	void enqueue(F&& f, Args&&... args)
	{
		std::function<void()> task(std::bind(std::forward<F>(f), std::forward<Args>(args)...));

		{
			std::unique_lock<std::mutex> lock(mutex);
			tasks.emplace(std::move(task));
		}
		condition.notify_one();
	}

private:
	std::vector<std::thread> threads;
	std::queue<std::function<void()>> tasks;
	std::mutex mutex;
	std::condition_variable condition;
	bool stop;
};


int main()
{
	ThreadPool pool(4);
	for (int i = 0; i < 8; ++i)
	{
		pool.enqueue([i] (){
			std::cout << "Task " << i << " is running in thread " << std::this_thread::get_id() << std::endl;
			std::this_thread::sleep_for(std::chrono::seconds(1));
			std::cout << "Task " << i << " is done" << std::endl;
		});
	}
	return 0;
}

使用function

使用function作为线程的入口函数

class ThreadPool
{
public:

	ThreadPool(int numThreads) : stop(false)
	{
		for (int i = 0; i < numThreads; ++i)
		{
		//使用function ,因为是非静态成员函数,所以需要指定调用对象,使用bind来适配。
			std::function<void()> fun = std::bind(&ThreadPool::threadExec,this);
			std::thread t(fun);//用fun来作为线程入口函数,
			threads.push_back(std::move(t));//线程入队
		}
	}
	 void threadExec()
	{
		while (true)
		{
			std::unique_lock<std::mutex> lock(mutex);
			condition.wait(lock, [this]() { return stop || !tasks.empty(); });
			if (stop && tasks.empty())
			{
				return;
			}
			std::function<void()> task(std::move(tasks.front()));
			tasks.pop();
			lock.unlock();
			task();
		}
	}
	~ThreadPool()
	{
		{
			std::unique_lock<std::mutex> lock(mutex);
			stop = true;
		}
		condition.notify_all();
		for (std::thread& thread : threads)
		{
			thread.join();
		}
	}

	template<typename F, typename... Args>
	void enqueue(F&& f, Args&&... args)
	{
		std::function<void()> task(std::bind(std::forward<F>(f), std::forward<Args>(args)...));

		{
			std::unique_lock<std::mutex> lock(mutex);
			tasks.emplace(std::move(task));
		}
		condition.notify_one();
	}

private:
	std::vector<std::thread> threads;
	std::queue<std::function<void()>> tasks;
	std::mutex mutex;
	std::condition_variable condition;
	bool stop;
};

分析

在这个示例中,我们同样定义了一个 ThreadPool 类,并且在构造函数中创建了指定数目的线程。在每个线程中,我们不断地从任务队列中获取任务并执行,直到线程池被停止。在 enqueue() 函数中,我们将任务封装成一个 std::function 对象,并将它添加到任务队列中。在 ThreadPool 的析构函数中,我们等待所有线程执行完成后再停止所有线程。

在主函数中,我们创建了一个 ThreadPool 对象,并向任务队列中添加了 8 个任务。每个任务会输出一些信息,并且在执行完后等待 1 秒钟。由于线程池中有 4 个线程,因此这 8 个任务会被分配到不同的线程中执行。在任务执行完成后,程序会退出。

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值