C++11线程池ThreadPool(模仿Java的ThreadPoolExecutor)

功能描述

实现一种基于C++11的线程池ThreadPool,模仿Java的ThreadPoolExecutor;

使用示例

#include"ThreadPool.h"
#include<iostream>
#include<assert.h>
using namespace std;
using Task = std::function<void()>;

std::mutex mx;
void func() {
   
   
	this_thread::sleep_for(std::chrono::milliseconds(20));
}
int main() {
   
   
	ThreadPool<Task, ArrayBlockingQueue<Task*>> threadPool(5, 10, 500, std::unique_ptr<ArrayBlockingQueue<Task*>>(new ArrayBlockingQueue<Task*>(200)));
	int success = 0;
	int total = 300;
	for (int i = 0; i < total; ++i) {
   
   
		Task task = std::bind(func);
		bool flag = threadPool.execute(task);
		std::cout << (flag ? "success" : "failed") << std::endl;
		success += flag;
		std::cout << threadPool.workerCount() << std::endl;
	}
	std::cout << "success/total: " << success << "/" << total << std::endl;
	std::this_thread::sleep_for(std::chrono::milliseconds(5000));
	std::cout << threadPool.workerCount() << std::endl;
}

关键函数说明

创建阻塞队列BlockingQueue

1)ArrayBlockingQueue实现了基于std::queue的有界阻塞队列;
2)参照该模板类的必要函数,用户可以根据阻塞队列类型不同,实现不同类型的阻塞队列(如:有界队列、无界队列、并发队列等);
3)为什么不写一个BlockingQueue抽象类供继承?
因为C++目前对于模板类中的模板函数不可以是虚函数;

ArrayBlockingQueue(int maxSize);

创建线程池ThreadPool

1)WorkQueuePtr为std::unique_ptr<BlockingQueue>类型;
2)其中BlockingQueue为阻塞队列,目前采用模板方式定义;
3)BlockingQueue放置的类型为Task*;
3)目前BlockingQueue仅仅实现了基于std::queue的有界阻塞队列;

	//corePoolSize:核心线程数;  当corePoolSize=0时,只有queue中放不下时,才会创建非核心线程
	//maximumPoolSize:最大线程数;  
	//keepAliveTime:活跃时间(单位毫秒);
	//workQueuePtr:阻塞队列;
	ThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, WorkQueuePtr&& workQueuePtr);

提交任务

1)Task为执行的任务类型,为模板类型;
2)返回值表示是否成功添加到队列中或被线程执行;

    //执行任务
	//返回为false的可能情况:队列中满了,且线程数量已经达到最大值
	bool execute(Task& task);

shutdown线程池

	//关闭线程池,线程中当前的任务会执行完,但不会继续取任务队列中的任务
	//是否需要支持暂停添加任务??
	void shutdown();

设计思想

BlockingQueue设计

1)该类实例以组合的方式被ThreadPool持有,主要是为了让用户可以传入自定义的BlockingQueue,提高ThreadPool的扩展性;
2)BlockingQueue放置的类型为Task*;

execute执行流程

1)判断当前核心线程数是否达到极限corePoolSize,如果没有,则创建核心线程并负责执行该任务,并返回true;(执行完这个任务之后,会阻塞在queue上取任务,直到返回)
2)否则,尝试加入BlockingQueue中,成功,则返回true;
3)否则,判断当前线程数达到极限maximumPoolSize,如果没有,则创建非核心线程并负责执行该任务,并返回true;(执行完这个任务之后,会阻塞在queue上取任务,直到返回;当等待超时keepAliveTime后,该线程退出,并销毁对应资源)
4)否则,返回false,表示任务提交失败;
注:执行过程中会判断当前线程池的状态是否为Running,如果不是,也是直接返回false;
注:只有在核心线程数量达到极限corePoolSize且队列BlockingQueue中push失败,才会创建非核心线程;

ctl变量设计

1)ctl类型为atomic_uint32_t,存储线程池状态以及当前线程数量;
2)ctl前3位表示当前ThreadPool状态,后COUNT_BITS=29位表示当前线程数量;
3)如此设计,是为了在方便一起对线程状态以及线程数进行CAS,以避免无意义地持有mainLock;

BlockingQueue必须实现函数说明

1)为适配ThreadPool,以下为用户自定义的BlockingQueue需要实现的函数;
2)其中interrupt()唤醒等待在具有Predicate参数 的push或者pop函数的线程;
3)interrupt()设计目的是唤醒等待在queue上的线程,使得主线程可以通知线程退出;

	const static int SUCCESS = 0;   //成功
	const static int TIMEOUT = 1;  //超时
	const static int INTERRUPT = 2;  //中断;当传入的Predicate为真时,返回(被interrupt唤醒)
	const static int RETRY = 3;  //请重试

	bool isEmpty();
	bool isFull();
	int size();

	int push(Task& task);
	int pop(Task& task);

	template<typename Predicate>
	int push(Task& task, Predicate pred);
	template<typename Predicate>
	int pop(Task& task, Predicate pred);

	bool tryPush(Task& task);
	bool tryPop(Task& task);

	int push(Task& task, int timeout);
	int pop(Task& task, int timeout);

	template<typename Predicate>
	int push(Task& task, int timeout, Predicate pred);
	template<typename Predicate>
	int pop(Task& task, int timeout, Predicate pred);

	void interrupt(); //仅仅打断,仅影响wait的pred

Task类型实现要求

1)可以直接使用Task()的形式进行执行;
2)一种符合要求的Task如下;

using Task = std::function<void()>;

源码

BlockingQueue.h

#pragma once
#include<thread>
#include<queue>
#include<mutex>
#include<condition_variable>

//类型Task支持nullptr的赋值和相等操作
//采用queue+mutex实现有界队列
template<typename Task>
class ArrayBlockingQueue{
   
   
public:
	const static int SUCCESS = 0;   //成功
	const static int TIMEOUT = 1;  //超时
	const static int INTERRUPT = 2;  //中断;当传入的Predicate为真时,返回(被interrupt唤醒)
	const static int RETRY = 3;  //请重试
private:
	std::queue<Task> queue;
	int maxSize;

	std::mutex mx;
	std::condition_variable p_cond;  //生产者cond
	std::condition_variable c_cond;  //消费者cond

	ArrayBlockingQueue(const ArrayBlockingQueue&) = delete;
	ArrayBlockingQueue& operator=</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值