C++:线程池类的定义

举报
内核笔记 发表于 2021/06/09 00:06:45 2021/06/09
【摘要】 文章目录 功能介绍类自动锁互斥锁的封装任务的封装接口类线程类封装线程槽 功能介绍 此类实现了如下功能: 在程序启动时即创建若干个线程(即线程池),当有任务需要执行时,将需要执行的任务放入任务队列,唤醒一个空闲线程进行任务的处理,处理完任务后线程继续进入睡眠 状态。 类 类名内容CAutoLock自动锁CMutex该类实现了互斥锁的封装CTask任...

功能介绍

此类实现了如下功能:
在程序启动时即创建若干个线程(即线程池),当有任务需要执行时,将需要执行的任务放入任务队列,唤醒一个空闲线程进行任务的处理,处理完任务后线程继续进入睡眠 状态。

类名 内容
CAutoLock 自动锁
CMutex 该类实现了互斥锁的封装
CTask 任务封装,ITask的实例
CTaskThread 任务线程类
CThread 线程类封装,实现了睡眠线程唤醒机制
ITask 接口类,定义了几个虚函数
ITaskThreadSink 任务线程槽接口,主要为了在启动任务前或任务结束后需要执行一些相关操作而实现

自动锁

/** @class CAutoLock
 * @brief 自动锁
 *
 * 该类实现了对CMutex类对象的自动上锁与解锁,它只提供了两个方法,构造与析构
 * 在构造函数里对CMutex类对象上锁,在析构函数里进行解锁
 */
class CAutoLock
{
public:
	/** @brief 构造函数,自动上锁 */
	CAutoLock(CMutex *pMutex)
	{
		m_pMutex = pMutex;
		m_pMutex->Lock();
	} /** @brief 析构函数,自动解锁 */
	virtual ~CAutoLock()
	{
		m_pMutex->Unlock();
	}

private:
	CMutex * m_pMutex;
};

#endif

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

互斥锁的封装

/** @class CMutex
 * @brief 该类实现了互斥锁的封装
 */
class CMutex
{
public:
	/** @brief 构造函数 */
	CMutex();
	/** @brief 析构函数 */
	virtual ~CMutex();

	/** @brief 上锁操作 * @return 0-成功,非0-失败
	 */
	int Lock();

	/** @brief 解锁操作 * @return 0-成功,非0-失败
	 */
	int Unlock();

	/** @brief 尝试上锁操作,非阻塞
	 * @return 0-成功,非0-失败
	 */
	int TryLock();

	/** @brief 获取互斥锁
	 * @return 返回互斥锁指针
	 */
	pthread_mutex_t * GetPthreadMutex() { return &m_mutex; }
	
protected:	

private:
	pthread_mutex_t m_mutex;
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

任务的封装

#define  PRIORITY_LOW   1
#define  PRIORITY_HIGH  4

/** @class CTask
 * @brief 任务封装,ITask的实例
 */
class CTask : public ITask
{
public:
	CTask(int p = PRIORITY_LOW);
	virtual ~CTask();

	/** @brief 预执行任务 */
	virtual void PreExec();

	/** @brief 需要执行的任务 */
	virtual void Execute() = 0 ;

	/** @brief 执行后处理 */
	virtual void PostExec();

	/** @brief 获取当前任务优先级 * @return 当前任务的优先级别
	 */
	virtual int   Priority(void);

	/** @brief 设备任务优先级 * @param p - 任务优先级,从1到4为从低到高 */
	virtual void  Priority(int p);

private:
	int   m_priority;
};


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

接口类

其中继承的ITask为:


/** @class ITask 任务封装接口
 * @brief 接口类,定义了几个虚函数
 */
class ITask
{
public:
	/** @brief 析构函数 */ virtual ~ITask() { }
	/** @brief 预执行任务 */ virtual void PreExec() { }
	/** @brief 执行主任务 */ virtual void Execute() = 0;
	/** @brief 执行后收尾工作 */ virtual void PostExec() { } 
	/** @brief 设置优先级 */ virtual void Priority(int p) = 0;
	/** @brief 获取优先级 */ virtual int Priority() = 0;
};


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

线程类封装

/** @class CTaskThread
 * @brief 任务线程类
 *
 * 该类的使用方法为:先创建一个ITask对象,并实现其需要执行的函数代码,
 * 需要实现的函数主要为:PreExec(), Execute(),PostExec(),
 * 接着通过调用SetTask()方法将ITask对象作为参数传入,使其作为线程需要执行的任务
 * 在SetTask()函数中会调用线程的SignalThread()函数唤醒线程以执行任务。
 * 在启动任务前,若设置了ITaskThreadSink对象,则会先执行其OnTaskStart()函数,
 * 在结束任务后,若设置了ITaskThreadSink对象,则会执行其OnTaskStop()函数
 */
class CTaskThread : public CThread
{
	public:
		/** @brief 构造函数 * @param pSink - 线程任务启动前或结束后需执行相关操作时,可传入此参数 */
		CTaskThread(ITaskThreadSink  *pSink = NULL); /** @brief 析构函数 */
		virtual ~CTaskThread(); /** @brief 启动线程执行pTask中的任务,传入不同的ITask对象可以让线程执行不同的任务\n * 执行完任务后,线程继续进入等待状态 * @param pTask - 需要执行的任务对象,会执行其PreExec(),Execute()和PostExec()函数 * @return 0 - 操作成功, 否则失败 * @note 返回0时并不代表任务执行一定正确,并且在执行完任务会,会删除pTask对象 */
		int  SetTask(ITask *pTask); /** @brief 获取当前CTaskThread对象的地址 * @return 本对象地址 */
		unsigned long  GetTaskThreadId() const ;

	protected:
		virtual void ExecuteTask();

	private:
		ITaskThreadSink  *m_pSink;
		ITask  *m_pTask; CMutex  m_cMutexTask;
		unsigned long m_nId;
};


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

其中继承CThread为:

/** @class CThread
 * @brief 线程类封装,实现了睡眠线程唤醒机制
 */
class CThread
{
public:
	/** @brief 构造函数, 条件变量在此时初始化 */
	CThread();

	/** @brief 析构函数 */
	virtual ~CThread();

protected:
	/** @brief 线程函数
	 *
	 * 在TheThread()线程函数中调用此函数,为执行任务循环的主体 * 为保证线程只有一个实例在运行,在此函数开始执行前会先上锁保护。
	 * 直到此函数结束才释放锁,故在调用Start函数时需注意
	 */
	virtual void  Thread();

	/** @brief 执行任务函数,在线程被唤醒时执行的函数 */
	virtual void  ExecuteTask();

public:
	/** @brief 启动线程任务循环 */
	virtual int Start();

	/** @brief 结束此线程,会等待线程退出 */
	virtual int Kill();

	/** @brief 检查线程是否在运行
	 * @return true - 在运行,false - 未运行
	 */
	bool   IsRunning() { return m_bRunning; } protected:
	/** @brief 创建线程时的线程函数 */
	static void * TheThread(void *param);

	/** @brief 设置线程的运行状态 * @param b true - 已运行, false - 未运行
	 */
	void   SetRunning(bool b);

	/** @brief 设置线程的结束标记 * @param b - true 结束线程
	 */
	void   SetEndFlag(bool b);

	/** @brief 获取线程结束标记
	 * @return true - 线程已结束 false - 线程未结束
	 */
	bool   IsEndFlagSet() { return m_bEndFlag; }

	/** @brief 发送信号唤醒线程开始执行任务 */
	void   SignalThread();

private:
	pthread_t m_hThread;	
	bool m_bRunning;
	bool m_bEndFlag;
	pthread_cond_t  m_Cond;
	CMutex m_cMutexStatus;	
	CMutex m_cMutexThread;
};


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

线程槽


/** @class ITaskThreadSink
 * @brief 任务线程槽接口,主要为了在启动任务前或任务结束后需要执行一些相关操作而实现
 */
class ITaskThreadSink
{
	public:
		/** @brief 析构函数 */
		virtual ~ITaskThreadSink() { } /** @brief 在启动任务前需执行的操作 */
		virtual int OnTaskStart(CTaskThread *thread) = 0; /** @brief 在任务执行完成后需执行的操作 */
		virtual int OnTaskStop(CTaskThread *thread) = 0;
};


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

文章来源: xuesong.blog.csdn.net,作者:内核笔记,版权归原作者所有,如需转载,请联系作者。

原文链接:xuesong.blog.csdn.net/article/details/99180874

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。