c++线程池小例子
ThreadPool.h
#ifndef __THREADPOOL_H
#define __THREADPOOL_H #define HAVE_STRUCT_TIMESPEC //#include "servant/Application.h"
#include <vector>
#include <string>
#include <pthread.h> using namespace std; /**
* 执行任务的类,设置任务数据、定义执行方法(纯虚函数)
*/
class CTask
{
protected:
string m_strTaskName; //任务的名称
void* m_ptrData; //具体数据
public:
CTask() {}
CTask(string taskName)
{
m_strTaskName = taskName;
m_ptrData = NULL;
}
virtual int Run() = 0; //任务执行方法
void SetData(void* data); //设置任务数据 public:
virtual ~CTask() {}
}; /**
* 线程结构体
*/
struct CThread
{
pthread_t pthread_id; //线程id
int iStat; //线程状态
CThread()
: iStat(0)
{ }
bool operator == (const CThread &obj) const
{
return (long)&pthread_id == (long)&obj.pthread_id;
}
}; /**
* 线程池管理类的实现
*/
class CThreadPool
{
public:
CThreadPool(int threadNum = 10);
int AddTask(CTask *task); //把任务添加到任务队列中
int getTaskSize(); //获取当前任务队列中的任务数
int StopAll(); //使线程池中的线程退出 protected:
int Create(); //创建线程池中的线程 static void* ThreadFunc(void * threadData); //新线程的线程回调函数 static int MoveToIdle(CThread *pThread); //线程执行结束后,状态置为空闲0
static int MoveToBusy(CThread *pThread); //线程开始执行,状态置为运行1 private:
static vector<CTask*> m_vecTaskList; //任务列表 static bool shutdown; //线程退出标志
int m_iThreadNum; //线程池中启动的线程数
static vector<CThread> m_vecThread; //线程列表 static pthread_mutex_t m_pthreadMutex; //线程同步锁
static pthread_cond_t m_pthreadCond; //线程同步的条件变量
}; #endif
ThreadPool.cpp
#include "ThreadPool.h"
#include <iostream>
#include <algorithm>
using namespace std; void CTask::SetData(void * data)
{
m_ptrData = data;
} vector<CTask*> CThreadPool::m_vecTaskList; //任务列表
bool CThreadPool::shutdown = false;
vector<CThread> CThreadPool::m_vecThread; //线程列表 pthread_mutex_t CThreadPool::m_pthreadMutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t CThreadPool::m_pthreadCond = PTHREAD_COND_INITIALIZER; /**
* 线程池管理类构造函数
*/
CThreadPool::CThreadPool(int threadNum)
{
this->m_iThreadNum = threadNum;
cout << "threadNum:" << threadNum << " threads will be created." << endl;
Create(); //创建线程
} /**
* 创建线程
*/
int CThreadPool::Create()
{
m_vecThread.resize(m_iThreadNum);
for (size_t i = 0; i < m_vecThread.size(); i++)
{
pthread_create(&m_vecThread[i].pthread_id, NULL, ThreadFunc, &m_vecThread[i]);
}
return 0;
} /**
* 线程回调函数
*/
void* CThreadPool::ThreadFunc(void* threadData)
{
CThread *pThread = (CThread*)threadData;
while (1)
{
pthread_mutex_lock(&m_pthreadMutex); //lock
while (m_vecTaskList.size() == 0 && !shutdown)
{
pthread_cond_wait(&m_pthreadCond, &m_pthreadMutex);
/*
pthread_cond_wait前要先加锁
pthread_cond_wait把线程放进阻塞队列后,内部会解锁,然后等待条件变量被其它线程唤醒
pthread_cond_wait被唤醒后会再自动加锁
*/
} if (shutdown)
{
pthread_mutex_unlock(&m_pthreadMutex);
cout << "thread:" << (long)&pThread->pthread_id << " will exit." << endl;
pthread_exit(NULL);
} //线程状态置1
MoveToBusy(pThread); //取出一个任务
CTask* task = NULL;
vector<CTask*>::iterator iter = m_vecTaskList.begin();
if (iter != m_vecTaskList.end())
{
task = *iter;
m_vecTaskList.erase(iter);
} pthread_mutex_unlock(&m_pthreadMutex); //unlock //执行任务
if (task)
{
task->Run();
}
//线程状态置0
MoveToIdle(pThread);
}
return (void*)0;
} int CThreadPool::MoveToIdle(CThread *pThread)
{
vector<CThread>::iterator iter_thread = std::find(m_vecThread.begin(), m_vecThread.end(), *pThread);
if (iter_thread != m_vecThread.end())
{
iter_thread->iStat = 0;
cout << "tid:" << (long)&pThread->pthread_id << " idle." << endl;
}
return 0;
} int CThreadPool::MoveToBusy(CThread *pThread)
{
vector<CThread>::iterator iter_thread = std::find(m_vecThread.begin(), m_vecThread.end(), *pThread);
if (iter_thread != m_vecThread.end())
{
iter_thread->iStat = 1;
cout << "tid:" << (long)&pThread->pthread_id << " run." << endl;
}
return 0;
} /**
* 往任务队列里边添加任务并发出线程同步信号
*/
int CThreadPool::AddTask(CTask *task)
{
pthread_mutex_lock(&m_pthreadMutex);
this->m_vecTaskList.push_back(task);
pthread_cond_signal(&m_pthreadCond);
pthread_mutex_unlock(&m_pthreadMutex);
return 0;
} /**
* 获取当前队列中任务数
*/
int CThreadPool::getTaskSize()
{
return m_vecTaskList.size();
} /**
* 停止所有线程
*/
int CThreadPool::StopAll()
{
/** 避免重复调用 */
if (shutdown)
{
return -1;
}
cout << "All threads will be stoped." << endl;
/** 唤醒所有等待线程,线程池要销毁了 */
shutdown = true;
pthread_cond_broadcast(&m_pthreadCond); /** 阻塞等待线程退出,否则就成僵尸了 */
for (size_t i = 0; i < m_vecThread.size(); i++)
{
pthread_join(m_vecThread[i].pthread_id, NULL);
}
m_vecThread.clear(); /** 销毁条件变量和互斥体 */
pthread_mutex_destroy(&m_pthreadMutex);
pthread_cond_destroy(&m_pthreadCond); return 0;
}
main.cpp
#include <iostream>
#include "ThreadPool.h" using namespace std; class CMyTask : public CTask
{
public:
CMyTask() {} inline int Run()
{
cout << (char*)this->m_ptrData << endl;
return 0;
}
}; int main()
{
CThreadPool threadPool(10); CMyTask taskObj; char szTmp[] = "this is the first thread running";
taskObj.SetData((void*)szTmp); for (int i = 0; i < 10; i++)
{
threadPool.AddTask(&taskObj);
} while (1)
{
cout << "there are still " << threadPool.getTaskSize() << " tasks need to handle" << endl;
if (threadPool.getTaskSize() == 0)
{
if (threadPool.StopAll() == -1)
{
cout << "Now I will exit from main" << endl;
return 0;
}
}
}
return 0;
}
makeflie
TARGET:=threadpool
INC:= -I./
LIB_PATH:=
LIB:= -lpthread CFLAGS:=-Wall -g -O0 -D_REENTRANT -Wl,-rpath=./ $(INC) $(LIB_PATH)
CPPFLAGS:=$(CFLAGS) SRC:=$(shell echo *.cpp)
OBJ:=$(patsubst %.cpp,%.o,$(SRC)) all: $(TARGET) $(TARGET): $(OBJ)
$(CXX) $^ $(CFLAGS) $(LIB) -o $@ clean:
rm -f $(OBJ)
rm -f $(TARGET)
windows下配置 pthread 参见:https://blog.csdn.net/qianchenglenger/article/details/16907821
线程同步、条件变量说明参见:https://www.cnblogs.com/zhangxuan/p/6526854.html
c++线程池小例子的更多相关文章
- Java 多线程编程之九:使用 Executors 和 ThreadPoolExecutor 实现的 Java 线程池的例子
线程池用来管理工作线程的数量,它持有一个等待被执行的线程的队列. java.util.concurrent.Executors 提供了 java.util.concurrent.Exe ...
- 13 并发编程-(线程)-异步调用与回调机制&进程池线程池小练习
#提交任务的两种方式 #1.同步调用:提交完任务后,就在原地等待任务执行完毕,拿到结果,再执行下一行代码,导致程序是串行执行 一.提交任务的两种方式 1.同步调用:提交任务后,就在原地等待任务完毕,拿 ...
- java 线程池简单例子
package com.hra.riskprice; import com.hra.riskprice.SysEnum.Factor_Type; import com.hra.riskprice.po ...
- Java ExecutorService四种线程池的例子与说明
1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...
- Java 1.ExecutorService四种线程池的例子与说明
1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...
- Java ExecutorService四种线程池的例子与说明(转发)
1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...
- java并发编程基础——线程池
线程池 由于启动一个线程要与操作系统交互,所以系统启动一个新的线程的成本是比较高的.在这种情况下,使用线程池可以很好的提升性能,特别是程序中涉及创建大量生命周期很短暂的线程时. 与数据库连接池类似,线 ...
- c++封装编写线程池
在csapp学习或者其他linux底层编程的过程中,一般都会举一些多线程或多进程的例子,配合底层同步原语.系统调用api来解释怎么创建多线程/多进程. 但是这些例子和实际项目中所用到的多线程/多进程编 ...
- 手写线程池,对照学习ThreadPoolExecutor线程池实现原理!
作者:小傅哥 博客:https://bugstack.cn Github:https://github.com/fuzhengwei/CodeGuide/wiki 沉淀.分享.成长,让自己和他人都能有 ...
随机推荐
- 天天爱跑步 [NOIP2016]
Description 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.<天天爱跑步>是一个养成类游戏,需要玩家每天按时上线,完成打卡任务.这个游戏的地图可 ...
- 使用Ajax和JSON实现注册时候验证用户名是否存在的功能
功能实现的思路:当通常一个网站需要注册用户信息的时候,往往会让用户起一个名字,但一般要求这个用户名称是不能重复的,为了判断新注册的用户填写的用户名是否已经存在,需要对填写的用户名称进行判断,实际项目开 ...
- 基于ELK5.1(ElasticSearch, Logstash, Kibana)的一次整合
前言开源实时日志分析ELK平台(ElasticSearch, Logstash, Kibana组成),能很方便的帮我们收集日志,进行集中化的管理,并且能很方便的进行日志的统计和检索,下面基于ELK的最 ...
- sql 索引笔记--索引组织结构
非聚集索引与聚集索引具有相同的 B 树结构,它们之间的显著差别在于以下两点: 基础表的数据行不按非聚集键的顺序排序和存储. 非聚集索引的叶层是由索引页而不是由数据页组成. 既可以使用聚集索引来为表或视 ...
- 12、mysql补充
本篇导航: 视图 触发器 事务 存储过程 函数 流程控制 一.视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,可 ...
- 透明Panel
unit TransparentPanel; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Varia ...
- javaScript系列 [01]-javaScript函数基础
[01]-javaScript函数基础 1.1 函数的创建和结构 函数的定义:函数是JavaScript的基础模块单元,包含一组语句,用于代码复用.信息隐蔽和组合调用. 函数的创建:在javaScri ...
- iOS10 11跳转系统设置等的URL收集
Settings App-Prefs:root Settings -> About App-Prefs:root=General&path=About Settings -> Ac ...
- .Net转Java.02.数据类型
.NET中常见的数据类型分类分别是值类型和引用类型 值类型包括(基元类型.struct.枚举) 引用类型包括(类.类.数组.接口.指针) Java分为,基本类型和类 C# Java 值类型 ...
- wordclock中文模式快一个小时怎么调整
wordclock屏幕保护,设置为中文模式,显示的时间比系统时间要快一个小时,其实软件自带的配置文件可以设置调整到正常时间…… 工具/原料 wordclock 方法/步骤 桌面上右键菜 ...