【Linux】线程池,知识点很全!!

本文详细介绍了线程池的概念,包括其本质、处理数据流程和如何实现线程的优雅退出。线程池通过维护一组可重用线程,减少了线程创建和销毁的开销,适用于处理大量短生命周期的任务。文中还模拟了线程池处理网络数据的过程,并讨论了线程池中线程的状态管理和退出策略。
摘要由CSDN通过智能技术生成

1. 什么是线程池?

线程池: 一种线程使用模式,一个程序中线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配,可并发执行的任务。

1.1 线程池的本质

线程池 = 线程安全队列 + 一大堆的线程
线程安全队列:元素 = 数据 + 处理数据的函数地址

优点:

  1. 线程池维护了多个线程,避免数据某时刻从网络中来到时,短时间创建和销毁线程带来的代价。
  2. 线程池不仅能够保证内核的充分利用,还能防止过度调度。
  3. 可用线程数量应该取决于可用的并发处理器、处理器内核、内存、网络sockets等的数量。

应用场景:

  1. 需要大量线程完成代码,且每段代码的执行时间比较短
  2. 对性能要求苛刻,例如要求服务器能迅速响应客户请求
  3. 接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用

1.2 线程池处理数据流程

在这里插入图片描述
上图流程: 从网络来的数据,直接调用push插入线程池队列,然后在处理完成之后,再发送回,发送队列,之后发送线程,回到网络通过了一个队列(也可以叫缓冲),优点:把前台和后端解耦开来

注意:

  1. 线程池中的线程,都是同一种角色的线程,也就是每个线程都执行同样的入口函数。
  2. 如果线程池中的线程都是执行同样一个入口函数的话,执行的功能是不是就比较单一了?如何满足大量的业务需求呢?
    上面问题简化也就是:如何让相同入口函数的线程,处理不同的请求?
    1.switch case:遇到不同数据,case不同方法,处理大量不同需求时,比较麻烦
    2.数据函数都抛入:向线程池抛入数据的时候,将处理该数据的函数地址和数据一起抛入,线程池当中的线程,只需要调用传入的函数去进行处理数据即可。
    因此:线程安全队列当中的元素:数据 + 处理函数的地址 handler_

1.3 线程安全队列元素类型

  1. 函数指针定义:typedef void* (*Handler_t)(int);返回值为void* 参数为int
  2. C++中线程的入口函数一定要static修饰的,因为线程入口函数规定参数只能有一个参数void* arg,而类里成员函数有隐含的this指针,不符合要求

2. 模拟实现处理网络数据

上面的图可以帮助理解代码

#include<stdio.h>
#include<unistd.h>
#include<queue>
#include<pthread.h>
#include<iostream>

#define THREADCOUNT 4

typedef void (*Handler_t)(int);  函数指针类型

class ThreadTask      			 队列的元素类型
{
   
private:
	Handler_t handler_; 		保存处理数据的函数
	int data_;          		待处理的数据
public:
	ThreadTask(Handler_t handler, int data)
		:handler_(handler)
		, data_(data)
	{
   }
	~ThreadTask()
	{
   }
	void Run()      			直接跑函数,处理数据。
	{
   
		handler_(data_);
	}
};
class ThreadPool
{
   
private:
	std::queue<ThreadTask
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值