基于C++11的线程池,指定线程执行任务

背景

基于C++11的线程池,如果线程与任务无关,比较好实现,但是!Opengl这种任务需要绘制上下文,就是需要指定线程执行任务。

代码

thread_pool.hpp

 

#ifndef _THREAD_POOL_H_
#define _THREAD_POOL_H_

#include <thread>
#include <mutex>
#include <atomic>
#include <condition_variable>
#include <functional>
#include <vector>
#include <queue>
#include <sstream>

class ThreadPool
{
public:
	using Task = std::function<bool()>;//KEY 通常的用法是std::function<void()>;那么回调函数没有返回值,无法判断是否执行完成

	explicit ThreadPool(int num) : thread_num_(num), is_running_(false)
	{}

	~ThreadPool()
	{
		if (is_running_)
			stop();
	}

	void start()
	{
		is_running_ = true;

		// start threads
		for (int i = 0; i < thread_num_; i++)
			threads_.emplace_back(std::thread(&ThreadPool::work, this));
	}

	std::vector<uint64_t> GetThreadIDs()
	{
		std::unique_lock<std::mutex> lk(mtx_);
		return thread_ids_;
	}

	void stop()
	{
		{
			// stop thread pool, should notify all threads to wake
			std::unique_lock<std::mutex> lk(mtx_);
			is_running_ = false;
			cond_.notify_all(); // must do this to avoid thread block
		}

		// terminate every thread job
		for (std::thread& t : threads_)
		{
			if (t.joinable())
				t.join();
		}
		thread_ids_.clear();
		threads_.clear();
	}

	void appendTask(const Task& task)
	{
		
		if (is_running_)
		{
			std::unique_lock<std::mutex> lk(mtx_);
			tasks_.push(task);
			//cond_.notify_one(); // wake a thread to to the task
			cond_.notify_all();//广播的方式通知所有线程
		}
	}

private:
	void work()
	{
		std::thread::id id = std::this_thread::get_id();
		std::stringstream ss;
		ss << std::this_thread::get_id();
		uint64_t thread_current = std::stoull(ss.str());
		thread_ids_.push_back(thread_current);

		// every thread will compete to pick up task from the queue to do the task
		while (is_running_)
		{
			Task task;
			std::unique_lock<std::mutex> lk(mtx_);
			if (!tasks_.empty())
			{
				// if tasks not empty, 
				// must finish the task whether thread pool is running or not
				task = tasks_.front();
			}
			else if (is_running_ && tasks_.empty())
			{
				cond_.wait(lk);
			}				
			
			if (task)
			{
				if (task())  // do the task 回调是否成功完成
				{
					tasks_.pop(); // remove the task
				}
				cond_.wait(lk);
			}
		}
	}

public:
	// disable copy and assign construct
	ThreadPool(const ThreadPool&) = delete;
	ThreadPool& operator=(const ThreadPool& other) = delete;

private:
	std::atomic_bool					is_running_; // thread pool manager status
	std::mutex							mtx_;
	std::condition_variable				cond_;
	int									thread_num_;
	std::vector<std::thread>			threads_;
	std::vector<uint64_t>				thread_ids_;
	std::queue<Task>					tasks_;
};


#endif // !_THREAD_POOL_H_

 

应用

//启动线程池
thread_pool_ = shared_ptr<ThreadPool>(new ThreadPool(20));;
thread_pool_->start();

...


//添加任务
thread_pool_->appendTask(std::bind(&Worker::ConsumerFunction, this, msg, thread_id));

...

//callback
bool Worker::ConsumerFunction(Message msg, uint64_t thread_id)
{
        std::unique_lock<std::mutex> g(mutex_);
        std::stringstream ss;
        ss << std::this_thread::get_id();
        uint64_t thread_current = std::stoull(ss.str());
        std::cout << "ConsumerFunction thread_current " << thread_current << std::endl;
        std::cout << "ConsumerFunction thread_id " << thread_id << std::endl;
        if (thread_current != thread_id)
        {
            return false;
        }

        //do real job
        std::cout << "do real job \n";
}

后续

任务和线程的匹配关系,需要另外维护

以下是一个基于C 11的线程池代码,包含线程池的创建、销毁、任务添加、任务执行等基本功能: ``` #include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <stdbool.h> // 定义任务结构体 typedef struct task { void *(*func)(void *); // 任务函数 void *arg; // 任务参数 struct task *next; // 下一个任务 } task_t; // 定义线程池结构体 typedef struct thread_pool { pthread_mutex_t lock; // 互斥锁 pthread_cond_t notify; // 条件变量 pthread_t *threads; // 线程数组 task_t *queue; // 任务队列 bool is_shutdown; // 线程池是否关闭标志 int thread_count; // 线程数 int queue_size; // 任务队列长度 } thread_pool_t; // 初始化线程池 void thread_pool_init(thread_pool_t *pool, int thread_count, int queue_size) { pthread_mutex_init(&(pool->lock), NULL); pthread_cond_init(&(pool->notify), NULL); pool->threads = (pthread_t *)malloc(sizeof(pthread_t) * thread_count); pool->queue = NULL; pool->is_shutdown = false; pool->thread_count = thread_count; pool->queue_size = queue_size; // 创建指定数量的线程 for (int i = 0; i < thread_count; i++) { pthread_create(&(pool->threads[i]), NULL, thread_pool_worker, (void *)pool); } } // 线程池工作函数 void *thread_pool_worker(void *arg) { thread_pool_t *pool = (thread_pool_t *)arg; while (true) { pthread_mutex_lock(&(pool->lock)); while (pool->queue == NULL && !pool->is_shutdown) { pthread_cond_wait(&(pool->notify), &(pool->lock)); } if (pool->is_shutdown) { pthread_mutex_unlock(&(pool->lock)); pthread_exit(NULL); } // 取出任务执行 task_t *task = pool->queue; pool->queue = pool->queue->next; pthread_mutex_unlock(&(pool->lock)); (*(task->func))(task->arg); free(task); } } // 添加任务线程池 void thread_pool_add_task(thread_pool_t *pool, void *(*func)(void *), void *arg) { task_t *task = (task_t *)malloc(sizeof(task_t)); task->func = func; task->arg = arg; task->next = NULL; pthread_mutex_lock(&(pool->lock)); if (pool->queue == NULL) { pool->queue = task; } else { task_t *temp = pool->queue; while (temp->next != NULL) { temp = temp->next; } temp->next = task; } pthread_cond_signal(&(pool->notify)); pthread_mutex_unlock(&(pool->lock)); } // 销毁线程池 void thread_pool_destroy(thread_pool_t *pool) { pool->is_shutdown = true; // 唤醒所有线程并等待它们退出 pthread_cond_broadcast(&(pool->notify)); for (int i = 0; i < pool->thread_count; i++) { pthread_join(pool->threads[i], NULL); } // 销毁任务队列 task_t *task; while (pool->queue != NULL) { task = pool->queue; pool->queue = task->next; free(task); } // 销毁互斥锁和条件变量 pthread_mutex_destroy(&(pool->lock)); pthread_cond_destroy(&(pool->notify)); free(pool->threads); } ``` 使用方法: 1. 首先定义一个 `thread_pool_t` 结构体变量; 2. 调用 `thread_pool_init` 函数初始化线程池,传入线程数和任务队列长度; 3. 调用 `thread_pool_add_task` 函数添加任务,传入任务函数和参数; 4. 线程池会自动执行添加的任务; 5. 最后调用 `thread_pool_destroy` 函数销毁线程池。 例如,下面的代码创建一个线程池,添加3个任务,然后销毁线程池: ``` void *task_func(void *arg) { int num = *((int *)arg); printf("Task %d is running.\n", num); usleep(100000); return NULL; } int main() { thread_pool_t pool; thread_pool_init(&pool, 2, 5); int args[3] = {1, 2, 3}; for (int i = 0; i < 3; i++) { thread_pool_add_task(&pool, task_func, (void *)&args[i]); } sleep(1); thread_pool_destroy(&pool); return 0; } ``` 输出结果为: ``` Task 1 is running. Task 2 is running. Task 3 is running. ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值