文章目录

  • 线程池的概念
    • 什么是线程池
    • 线程池的优点
    • 线程池的应用场景
  • 线程池的实现
    • 实现思路
    • 代码实现

线程池的概念

什么是线程池

顾名思义,线程池就是一个有很多空闲线程的池子(线程的数量受到限制),需要用到多执行流进行任务处理时,就从池子中唤醒一个线程去处理任务

线程池的优点

  • 避免大量线程频繁创建和销毁带来的时间成本
    :如果在一开始即创建好线程,要用的时候直接从线程池中取出,用完再放回,这样就大大减少了创建与销毁带来的时间成本
  • 避免无限制的线程创建导致资源耗尽
    :线程池限制了线程的数量,这样就保证了不会因为线程创建过多导致资源耗竭,程序崩溃的情况

线程池的应用场景

有大量的数据处理请求,需要多执行流并发/并行处理


线程池的实现

实现思路

首先线程池的核心,就是大量的线程和一个任务缓冲队列。在线程池创建时就提前创建好一定数量的线程,如果有任务到来则将任务放入缓冲队列中,此时唤醒线程池中的线程取出任务进行处理,如果线程池没有空闲线程,则阻塞任务,直到有线程处理完任务回归线程池中。同时,因为不同任务有不同的处理方法,所以要开放接口给外界,处理的数据和方法由外界自己定,线程池只负责调用对应的任务处理方法进行处理,不关心其中的内容。这样就更具有灵活性。

代码实现

下面就来实现一个线程池,具体的细节都有注释

#include<iostream>
#include<pthread.h>
#include<cstdlib>
#include<queue>//类型重命名,将处理的方法定义为一个函数指针
typedef void (*handler_t)(int);const size_t MAX_SIZE = 10;//任务
class ThreadTask
{public://设置需要处理的数据与对应的处理方法void SetTask(int data, handler_t handler){_data = data;_handler = handler;}//处理数据void Run(){_handler(_data);}private:int _data;handler_t _handler;
};//线程池
class ThreadPool
{public:ThreadPool(size_t capacity = MAX_SIZE) : _capacity(capacity){pthread_cond_init(&_cond, NULL);pthread_mutex_init(&_mutex, NULL);//线程池提前创建线程for(size_t i = 0; i < _capacity; i++){pthread_t pid;int ret = pthread_create(&pid, NULL, start_routine, this);if(ret){std::cout << "线程创建失败" << std::endl;exit(-1);}}}~ThreadPool(){pthread_cond_destroy(&_cond);pthread_mutex_destroy(&_mutex);}void Push(ThreadTask& Task){//互斥锁保证线程安全pthread_mutex_lock(&_mutex);//将任务放入队列中_queue.push(Task);pthread_mutex_unlock(&_mutex);//唤醒线程池全部线程,谁抢到谁就来处理这个任务pthread_cond_broadcast(&_cond);}//入口函数的参数只能有一个void*,所以需要写为static函数来去掉隐含的this指针static void* start_routine(void *arg){//将void*强转为需要的类型ThreadPool* pool = (ThreadPool*)arg;while(1){pthread_mutex_lock(&pool->_mutex);   //如果任务队列为空则使线程循环等待while(pool->_queue.empty()){pthread_cond_wait(&pool->_cond, &pool->_mutex);}ThreadTask Task;//将任务出队进行处理Task = pool->_queue.front();pool->_queue.pop();pthread_mutex_unlock(&pool->_mutex);//解锁后再处理,因为加锁只是保证队列操作的安全性Task.Run();}return NULL;}private://互斥锁保证线程安全,条件变量保证任务的提交与处理同步pthread_cond_t _cond;pthread_mutex_t _mutex;size_t _capacity;std::queue<ThreadTask> _queue;
};

下面写一个函数来测试一下

#include "ThreadPool.hpp"
#include<unistd.h>void handler1(int data)
{std::cout << "线程ID:"<< pthread_self() <<" 处理奇数数据:" << data << std::endl;sleep(1);
}void handler2(int data)
{std::cout << "线程ID:"<< pthread_self() <<" 处理偶数数据:" << data << std::endl;sleep(1);
}int main()
{ThreadPool pool;for(int i = 0; i < 10; i++){ThreadTask task;//分别处理奇数和偶数if(i & 1){task.SetTask(i, handler1);}else{task.SetTask(i, handler2);    }//任务放入队列中pool.Push(task);}//休眠一段时间防止结束后主线程退出sleep(100);return 0;
}

使用两种不同的处理方法来分别处理0-9的奇偶数

运行截图

C++实现一个简易的线程池相关推荐

  1. 分享:一个简单的线程池的实现

    一个简单的线程池的实现 http://my.oschina.net/hejiula/blog/110519

  2. 高并发编程-自定义简易的线程池(2),体会原理

    文章目录 概述 示例 概述 高并发编程-自定义简易的线程池(1),体会原理 中只实现了任务队列,我们这里把其余的几个也补充进来 拒绝策略 关闭线程池 最小 最大 活动线程数 - 示例 比较简单,直接上 ...

  3. 手写一个简单的线程池MyThreadPool

    说明 手写的一个简单的线程池,旨在帮助了解线程池的工作原理. 核心内容 核心工作线程 任务阻塞队列 定义一个内部类去实现核心工作线程 /*** 内部类:工作的核心线程*/private final c ...

  4. 如何写一个高效进程/线程池_关于高效企业测试的思考(1/6)

    如何写一个高效进程/线程池 企业中的测试仍然没有得到应有的广泛应用. 编写尤其是维护测试需要花费时间和精力,但是缩短软件测试并不是解决方案. 为了提高测试效率,应该追求哪些范围,方法和测试技术? 基于 ...

  5. 一个简单的线程池设计方案

    一个简单的线程池本质上是生产者-消费者模型,一般是线程池负责消费任务,任务分配线程负责生产任务,任务可以由队列.链表或全局变量等数据结构承担.如果生产和消费速度差不多,可以采用环形队列结构:如果任务有 ...

  6. 用Python实现一个简单的线程池

    线程池的概念是什么? 在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源.在Java中更是 如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收 ...

  7. 高并发编程-自定义简易的线程池(1),体会原理

    文章目录 概述 示例 概述 我们工作中,并发编程必然离不开jdk提供的j.u.c中的线程池 ,假设让我们自己去设计一个线程池,该从哪几个方面来着手考虑呢? 首先: 既然是线程池 , 那必然 有个初始化 ...

  8. 程序员修仙之路--设计一个实用的线程池

    菜菜呀,我最近研究技术呢,发现线上一个任务程序线程数有点多呀 CEO,CTO,CFO于一身的CXO x总,你学编程呢? 菜菜 作为公司总负责人,我以后还要管理技术部门呢,怎么能不会技术呢 CEO,CT ...

  9. Linux C 实现一个简单的线程池

    https://www.cnblogs.com/GyForever1004/p/9185240.html 线程池的定义 线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动 ...

最新文章

  1. 100万人同时抢1万张火车票,极限并发带来的思考
  2. MySQL · 引擎特性 · InnoDB 事务子系统介绍
  3. Java 文件操作-File
  4. 【Antlr】cannot create implicit token for string literal in non-combined grammar xx
  5. Ancient Berland Circus CodeForces - 1C
  6. python3.8安装pyinstaller失败_pip命令安装 pyinstaller失败解决办法
  7. codevs1068 乌龟棋 题解
  8. 科学语言与matlab计算 实验2、3
  9. smb协议讲解_SMB/CIFS协议解析
  10. 【软件测试】:测试改进措施总结
  11. SAP基本计量单位更改
  12. Introduction to Robotics 总结1~6
  13. Jpress项目学习纪录片(一) -- 环境搭建
  14. 工行二维码支付时代来了
  15. 计算机专业高级工程师考哪些专业,高级工程师职称考试项目有哪些
  16. matlab密度特征,关于用MATLAB应用程序估算风险中性密度的性能分析和介绍
  17. 高性能计算服务器8280,AMD秀实力:第二代霄龙64核性能是英特尔Xeon Platinum8280两倍...
  18. WPS表格:数据基本计算与引用-函数与表达式
  19. PHP日期转换为时间戳
  20. 新手机为什么一注册陌陌就封解析硬改软改

热门文章

  1. plsql(轻量版)_触发器
  2. SpringBoot服务整合(整合邮件服务、定时调度、Actuator监控)
  3. 闭包案例产生多个相同的随机数 沙箱
  4. c语言仓库管理系统链表,仓库管理系统 C语言 C++ 数据结构 链表 课程设计
  5. 【Homework】什么是多态,多态具体体现有哪些?
  6. python unitest框架_python单元测试框架Unitest
  7. Cortex-M3-MPU(存储器保护单元)
  8. 常用LINQ关键字用法汇总
  9. iPhone X系列 的获取 - 安全区顶部和底部高度
  10. 阿里RocketMQ是怎样孵化成Apache顶级项目的?