cpp11实现线程池(三)——生产者与消费者线程函数实现

介绍

线程池中,生产者线程(主线程 Master)的主要工作是给任务队列提交任务函数实现;

而消费者线程(Slave)主要工作是从任务队列取任务并执行任务函数

给任务队列提交任务函数实现(Master)

// 给线程池提交任务
// 这是一个对队列的操作,有临界资源
void ThreadPool::submitTask(std::shared_ptr<Task> sp)
{
    
    
	// 获取锁
	std::unique_lock<std::mutex> lck(taskQueMtx_);
	// 线程的通信, 等待队列有空余
	//while (taskQue_.size() == taskQueMaxThreadhold_)
	//{
    
    
	//	notFull_.wait(lck); // 等待队列不满
	//}

	// 等价于上面的while
	// 满足第二项的pred才能退出while
	// 等1s没出来就退出返回
	if (!notFull_.wait_for(lck, std::chrono::seconds(1), [&]()->bool {
    
     return taskQue_.size() < taskQueMaxThreadhold_ }))
	{
    
    
		std::cerr << "task queue is full, submit task fail" << std::endl;
		return;
	}

	// 如果有空余,把任务放入任务队列中
	taskQue_.emplace(sp);
	taskSize_++; // ???

	// 任务队列不空,唤醒notEmpty_的wait,即通知消费者消费
	notEmpty_.notify_all();
}

线程执行任务的函数

void ThreadPool::threadFunc()
{
    
    
	/*std::cout << " begin threadFunc tid:" << std::this_thread::get_id() << std::endl;
	std::cout << " endthreadFunc tid:" << std::this_thread::get_id() << std::endl;*/
	for (;;)
	{
    
    
		std::shared_ptr<Task> task;
		{
    
    
			// 获取锁
			std::unique_lock<std::mutex> lck(taskQueMtx_);
			std::cout << "tid:" << std::this_thread::get_id() << "尝试获取任务..." << std::endl;
			// 等待notEmpty_条件
			notEmpty_.wait(lck, [&]()->bool {
    
     return taskQue_.size() > 0; });

			std::cout << "tid:" << std::this_thread::get_id() << "获取任务成功..." << std::endl;
			// 从任务队列中取一个任务出来
			task = taskQue_.front();
			taskQue_.pop();
			taskSize_--;

			// 若依然有剩余任务,继续通知其他线程执行任务
			if (taskQue_.size() > 0)
			{
    
    
				notEmpty_.notify_all();
			}

			// 取出一个任务进行通知 生产者可以进行生产任务
			notFull_.notify_all();
		} // 只需要对taskQue_及相关临界资源操作才加锁,执行不需要加锁

		// 当前线程负责执行这个任务
		if (task != nullptr)
		{
    
    
			task->run();
		}
		
	}	
}

相关测试

#include <iostream>
#include <chrono>
#include "threadpool.h"

class MyTask : public Task
{
    
    
public:
	void run()
	{
    
    
		std::cout << "tid:" << std::this_thread::get_id() << " begin!" << std::endl;
		std::this_thread::sleep_for(std::chrono::seconds(5));
		std::cout << "tid:" << std::this_thread::get_id() << " end!" << std::endl;
	}
};
int main()
{
    
    
	ThreadPool pool;
	pool.start(4);
	
	// 提交10个任务
	pool.submitTask(std::make_shared<MyTask>());
	pool.submitTask(std::make_shared<MyTask>());
	pool.submitTask(std::make_shared<MyTask>());
	pool.submitTask(std::make_shared<MyTask>());
	pool.submitTask(std::make_shared<MyTask>());
	pool.submitTask(std::make_shared<MyTask>());
	pool.submitTask(std::make_shared<MyTask>());
	pool.submitTask(std::make_shared<MyTask>());
	pool.submitTask(std::make_shared<MyTask>());
	pool.submitTask(std::make_shared<MyTask>());

	
	getchar();
	return 0;
}

分析

我们的任务队列大小已经设置为4,每个任务要sleep 5秒,刚开始4个任务放入任务队列,被线程取走执行,然后又能放入4个任务,此时任务队列已满,但是此时前面执行的4个任务都没执行完。剩余2个任务试图放入任务,阻塞1s后便失败。

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_42120843/article/details/130790116