首页 > 编程语言 >C++实现线程池

C++实现线程池

时间:2024-09-14 12:56:07浏览次数:10  
标签:std task Level 实现 C++ ThreadPool 线程 include

目录

这篇文章简单讨论下线程池。

一.什么是线程池

线程池简单来时就是维护了一组线程的池子,这组线程执行一些相似任务。是一种线程的使用方式。

二.为什么要用线程池

有的时候系统需要处理大量相似任务,频繁创建销毁线程会影响系统性能,这个时候就可以维护一组线程专门处理这些任务。

三.如何实现线程池

重点来了,这里展示一种简易的线程池实现方式,主要是为了描述一下线程池的一种运行模式。

直接看代码。

//threadpool.h

#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <vector>
#include <utility>
#include <mutex>
#include <functional>
#include <queue>
#include <condition_variable>
#include <thread>

#define ERR_MES_1 "输入值不合法"

enum Level
{
	Level_0,
	Level_1,
	Level_2
};

using Task = std::function<void()>;
using TaskPair = std::pair<Level, Task>;

class TaskPriorityCompare
{
public:
	bool operator()(TaskPair taskPair1, TaskPair taskPair2)
	{
		return taskPair1.first > taskPair2.first;
	}
};

using ThreadVec = std::vector<std::thread*>;
using TaskQue = std::priority_queue<TaskPair, std::vector<TaskPair>, TaskPriorityCompare>;
using FinishTaskQue = std::queue<Task>;
using UniqueLock = std::unique_lock<std::mutex>;

class ThreadPool
{
public:
	ThreadPool() = default;
	~ThreadPool()noexcept = default;
	bool Start(int ThreadPoolSize = 3);
	void Stop();
	void AddTask(const Task& task, Level level = Level_2);

protected:
	void LoopExecuteThread();
	Task TakeTask();

private:
	bool m_isStart;
	std::mutex m_mutex;
	std::condition_variable m_condVari;
	int m_threadPoolSize;
	ThreadVec m_threadVec;
	TaskQue m_taskQue;
	FinishTaskQue m_finishTaskQue;
	int m_lastErrCode;
	std::string m_lastErrMes;
};

#endif // !THREADPOOL_H
//threadpool.cpp

#include "threadpool.h"

#include <iostream>

bool ThreadPool::Start(int threadPoolSize)
{
	if (threadPoolSize < 1)
	{
		m_lastErrCode = 1;
		m_lastErrMes = ERR_MES_1;
		return false;
	}

	m_isStart = true;
	m_threadPoolSize = threadPoolSize;

	for (int i = 0; i < m_threadPoolSize; i++)
	{
		m_threadVec.push_back(new std::thread(&ThreadPool::LoopExecuteThread, this));
	}

	return true;
}

void ThreadPool::Stop()
{
	m_isStart = false;
	m_condVari.notify_all();
	
	for (auto ite = m_threadVec.begin(); ite != m_threadVec.end(); ite++)
	{
		(*ite)->join();
		delete* ite;
	}
	
	m_threadVec.clear();
}

void ThreadPool::AddTask(const Task& task, Level level)
{
	UniqueLock lock(m_mutex);
	TaskPair taskPair(level, task);
	m_taskQue.push(taskPair);
	m_condVari.notify_one();
}

void ThreadPool::LoopExecuteThread()
{
	UniqueLock lock(m_mutex);
	lock.unlock();
	
	while (m_isStart)
	{
		lock.lock();
		if (m_taskQue.empty())
		{
			m_condVari.wait(lock);
		}

		std::cout << std::this_thread::get_id() << std::endl;
		
		Task task = TakeTask();
		lock.unlock();
		
		if (task)
		{
			task();
			m_finishTaskQue.push(task);
		}
	}
}

Task ThreadPool::TakeTask()
{
	if (!m_taskQue.empty())
	{
		Task task;
		task = m_taskQue.top().second;
		m_taskQue.pop();
		
		return task;
	}

	return nullptr;
}
//main.cpp

#include "threadpool.h"

#include <iostream>

void Fun1()
{
	std::cout << "Fun1 exec" << std::endl;
}

void Fun2()
{
	std::cout << "Fun2 exec" << std::endl;
}

void Fun3()
{
	std::cout << "Fun3 exec" << std::endl;
}

int main(void)
{
	ThreadPool threadPool;
	int i = 3;

	threadPool.Start(i);

	for (int i = 0; i < 10; i++)
	{
		threadPool.AddTask(Fun1, Level_2);
		threadPool.AddTask(Fun2, Level_1);
		threadPool.AddTask(Fun3, Level_0);
	}

	std::this_thread::sleep_for(std::chrono::seconds(3));
	threadPool.Stop();

	return 0;
}

标签:std,task,Level,实现,C++,ThreadPool,线程,include
From: https://blog.csdn.net/2401_85919417/article/details/142024276

相关文章

  • uniapp - 最新详细实现web-view网页与安卓苹果App端之间互相通信功能,苹果app/安卓app
    前言在uni-app项目开发中,详解实现web-view和App之间的互相通信完整流程及代码教程,Uniappapp端向webview网站传递数据,同时webview又可以向app端传递数据参数,完成二者的数据通信方案,支持嵌入本地移动端H5页面、第三方网站、自定义网页,附带各种常见问题,解决发送数据通信没......
  • c++代理类
    c++中代理类的学习https://blog.csdn.net/lcg910978041/article/details/51468680C++代理类是为了解决这样的问题: 容器通常只能包含一种类型的对象,所以很难在容器中存储对象本身。怎样设计一个c++容器,使它有能力包含类型不同而彼此相关的对象? 代理运行起来和他所代表的......
  • VS+QT--实现二进制和十进制的转换(含分数部分)
    实现效果: 主要文件:BtD_DtB_converter.cpp#include"BtD_DtB_converter.h"#include<qpushbutton.h>#include<qlineedit.h>#include<qstring.h>#pragmaexecution_character_set("utf-8")BtD_DtB_converter::BtD_DtB_converter(Q......
  • 如何在局域网中(学校机房)实现文件共享(机位共享文件夹可被其他机位访问)
    操作环境:学校机房,win7(旗舰版)操作系统(无需担心电脑问题,机房电脑重启后即可恢复默认设置)。流程:1,创建你需要共享的文件夹。在D盘创建share文件夹。D:\share2,右键share文件夹点击属性找到共享页面,点击共享,添加Everyone用户,可修改其对文件夹的访问权限。2.1,在share属性......
  • 队列的定义和基本操作的实现
    写代码:定义顺序存储的队列(数组实现),要求数组空间可以被循环利用 写代码:基于上述定义,实现“出队、入队、判空、判满”四个基本操作 写代码:定义链式存储的队列(单链表实现) 写代码:基于上述定义,实现“出队、入队、判空、判满”四个基本操作 1.定义顺序存储的队列(数组实现),要......
  • Java HashMap详解:源码分析、hash 原理、扩容机制、加载因子、线程不安全
    这篇文章将会详细透彻地讲清楚Java的HashMap,包括hash方法的原理、HashMap的扩容机制、HashMap的加载因子为什么是0.75而不是0.6、0.8,以及HashMap为什么是线程不安全的,基本上HashMap的常见面试题,都会在这一篇文章里讲明白。HashMap是Java中常用的数据结构之一......
  • Matlab:实现夫琅禾费圆孔衍射仿真
    绘图结果原理%%夫琅禾费衍射例子——经过圆孔clc;%清除命令行窗口clearall;%清除工作区中的所有变量closeall;%关闭所有打开的图形窗口%参数设置L=0.2;%计算区域的物理尺寸(m)N=200;%网格点的数量dx......
  • 基于springboot智慧社区管理系统的设计与实现-附源码04191
    目 录1绪论1.1研究背景与意义1.2国内外研究现状1.3论文结构与章节安排2 系统分析2.1可行性分析2.1.1技术可行性分析2.1.2 经济可行性分析2.1.3法律可行性分析2.2系统需求分析2.3 系统用例分析2.4 系统流程分析2.4.1系统开发流程2.4.2......
  • 基于springboot列星药膳管理系统的设计与实现-附源码05345
    摘 要身处互联网+时代,互联网无形中影响着人们的吃穿住行,人们享受着不出门便可购物的便利,网络购物在当今社会工作生活节奏飞快的今天备受欢迎,让人们购物不再受时间、地点的制约,高效快速。药膳作为一种传统的中医养生方式受到了广泛关注。然而,传统的药膳管理方式存在一些问题......
  • C++中定义一个空结构体的内存占用
    比如定义:structTest{};使用sizeof(Test)可以查看到内存占用并不是0,而是1字节。原因主要有两点:一是用于对象标识:在C++中,每个对象都需要有一个唯一的地址。如果空类或结构体的大小为0字节,那么创建两个这样的对象时,它们在内存中的地址将是相同的,这与C++的对象模型相冲突。为......