Linux系统编程---18(线程池相关概念及其实现)

线程池

概念:

一堆线程+任务队列

作用

  1. 避免大量线程频繁的创建/销毁时间成本
  2. 避免瞬间大量线程创建耗尽资源,程序崩溃危险

实现

创建固定数量的线程+创建一个线程安全的任务队列
在这里插入图片描述

一种线程使用模式。

  1. 线程过多会带来调度开销,进而影响缓存局部性和整体性能。
  2. 线程池维护着多个 线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。
  3. 线程池不 仅能够保证内核的充分利用,还能防止过分调度。可用线程数量应该取决于可用的并发处理器、处理器内核、内 存、网络sockets等的数量

线程池应用场景

  1. 需要大量的线程来完成任务,且完成任务的时间比较短。 WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。 但对于长时间的任务,比如一个Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大 多了。
  2. 对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
  3. **接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。**突发性大量客户请求,在没 有线程池情况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程 可能使内存到达极限,出现错误

线程池的分类

  1. FixThreadPool------固定线程池
  2. CachedThreadPool-----缓存线程池
  3. ScheduledThreadPool—调度线程池
  4. SingleThreadPool-----单任务线程池

特点介绍

FixedThreadPool

  1. 通过Exector的newFixedThreadPool静态方法来创建
  2. 线程数量固定的线程池
  3. 只有核心线程切并且不会被回收
  4. 当所有线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来

CachedThreadPool

  1. 通过Exector的newCachedThreadPool静态静态方法来创建
  2. 线程数量不定的线程池
  3. 只有非核心线程,最大线程数量为Integer.MAX_VALUE,可视为任意大
  4. 有超时机制,时长为60s,即超过60s的空闲线程就会被回收
  5. 当线程池中的线程都处于活动状态时,线程池会创建新的线程来处理新任务,否则就会利用空闲的线程来处理新任务。因此任何任务都会被立即执行
  6. 该线程池比较适合执行大量耗时较少的任务

ScheduledThreadPool

  1. 通过Exector的newScheduledThreadPool静态方法来创建
  2. 核心线程数量是固定的,而非核心线程数不固定的,并且非核心线程有超时机制,只要处于闲置状态就会被立即回收
  3. 该线程池主要用于执行定时任务和具有固定周期的重复任务

SingleThreadPool

  1. 通过Exector的newSingleThreadPool静态方法来创建
  2. 只有一个核心线程,它确保所有的任务都在同一个线程中按顺序执行。因此在这些任务之间不需要处理线程同步的问题

线程池实现

在这里插入图片描述

#include <iostream>
#include <queue>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <pthread.h>typedef bool (*task_callback)(int data);
class Task
{public:Task(){}   Task(int data, task_callback handler){_data = data;_handler = handler;}   ~Task(){}   public://设置任务处理的数据以及处理方法void SetTask(int data, task_callback handler){_data = data;_handler = handler;}   //执行任务bool Run() {return _handler(_data);}   private:int _data;task_callback _handler;
};
#define MAX_THR 5
#define MAX_QUE 10
class ThreadPool
{public:ThreadPool(int qmax = MAX_QUE, int tmax = MAX_THR):_thr_max(tmax), _capacity(qmax), _thr_cur(tmax){pthread_mutex_init(&_mutex, NULL);pthread_cond_init(&_cond_con, NULL);pthread_cond_init(&_cond_pro, NULL);}~ThreadPool(){pthread_mutex_destroy(&_mutex);pthread_cond_destroy(&_cond_con);pthread_cond_destroy(&_cond_pro);}public:static void *thr_start(void *arg) {ThreadPool *pool = (ThreadPool*)arg;while(1) {pool->QueueLock();while(pool->QueueIsEmpty()){pool->ConWait();}Task tt;pool->QueuePop(&tt);pool->ProWakeUp();pool->QueueUnLock();//为了防止处理时间过长导致其它线程无法获取锁//因此解锁之后才进行处理tt.Run();}return NULL;}bool ThreadPoolInit() {pthread_t tid;int ret, i;for (i = 0; i < _thr_max; i++) {ret = pthread_create(&tid, NULL, thr_start,(void*)this);if (ret != 0) {std::cout<<"thread create error\n";return false;                                 }pthread_detach(tid);}return true;}void AddTask(Task tt) {//向线程池添加任务QueueLock();while(QueueIsFull()) {ProWait();}QueuePush(tt);ConWakeUp();QueueUnLock();}void ThreadPoolQuit(){//退出线程池中所有的线程_quit_flag = true;while(_thr_cur > 0) {ConWakeUpAll();       usleep(1000);}return;}private:void QueuePush(Task tt){_queue.push(tt);}void QueuePop(Task *tt){*tt = _queue.front();_queue.pop();}void QueueLock(){pthread_mutex_lock(&_mutex);}void QueueUnLock(){pthread_mutex_unlock(&_mutex);}void ProWait(){pthread_cond_wait(&_cond_pro, &_mutex);}      void ProWakeUp(){pthread_cond_signal(&_cond_pro);}void ConWait(){//进入这个函表示现在没有任务if (_quit_flag == true) {//若线程池要求退出_thr_cur--;std::cout<<"thread:"<<pthread_self()<<"exit\n";pthread_mutex_unlock(&_mutex);pthread_exit(NULL);}pthread_cond_wait(&_cond_con, &_mutex);}void ConWakeUp(){pthread_cond_signal(&_cond_con);}void ConWakeUpAll(){pthread_cond_broadcast(&_cond_con);}bool QueueIsFull(){return (_queue.size() == _capacity);}bool QueueIsEmpty(){return _queue.empty();}private:int _thr_max;int _thr_cur;int _quit_flag;std::queue<Task> _queue;int _capacity;pthread_mutex_t _mutex;pthread_cond_t _cond_pro;pthread_cond_t _cond_con;
};
bool task_handler(int data){//休眠一段时间srand(time(NULL));int sec = rand()%5;std::cout<<"thread:"<<pthread_self()<<" sleep "<<sec<<"second\n";sleep(sec);return true;
}
int main()
{ThreadPool pool;Task tt[10];pool.ThreadPoolInit();int i;for (i = 0; i < 10; i++) {tt[i].SetTask(i, task_handler);pool.AddTask(tt[i]);}pool.ThreadPoolQuit();return 0;
} 

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/383216.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

设计模式--1(设计模式基础,设计模式基本原则,设计模式分类)

设计模式基础 模式 在一定环境中解决某一问题的方案&#xff0c;包括三个基本元素–问题&#xff0c;解决方案和环境。大白话&#xff1a;在一定环境下&#xff0c;用固定套路解决问题。 设计模式 是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使…

设计模式----2(简单工厂模式的概念,简单工厂模式的实现,简单工厂模式的优缺点)

简单工厂模式 简单工厂模式的概念 简单工厂模式属于类的创建型模式,又叫做静态工厂方法模式。通过专门定义一个类来负 责创建其他类的实例&#xff0c;被创建的实例通常都具有共同的父类。 具体分类 工厂&#xff08;Creator&#xff09;角色 简单工厂模式的核心&#xff0…

设计模式---3(工厂方法模式的概念,工厂方法模式的实现,工厂方法模式和简单工厂模式比较)

工厂方法模式 概念 工厂方法模式同样属于类的创建型模式又被称为多态工厂模式 。 工厂方法模式的意义 定义一个创建产品对象的工厂接口&#xff0c;将实际创建工作推迟到子类当中。 核心工厂类不再负责产品的创建&#xff0c;这样核心类成为一个抽象工厂角色&#xff0c;仅…

设计模式---4(抽象工厂模式的概念,产品组和产品等级的概念,抽象工厂模式的实现)

抽象工厂模式 抽象工厂模式的概念 抽象工厂模式是所有形态的工厂模式中最为抽象和最其一般性的。抽象工厂模式可以向 客户端提供一个接口&#xff0c;使得客户端在不必指定产品的具体类型的情况下&#xff0c;能够创建多个产品 族的产品对象。 抽象工厂的角色及其职责 抽象工…

1.c++中初始化列表和构造函数初始化的区别是什么?2.类的成员变量的初始化顺序是按照声明顺序吗?

初始化列表和构造函数初始化的区别是什么&#xff1f; 初始化和赋值对内置类型的成员没有太大的区别&#xff0c;在成员初始化列表和构造函数体内进行&#xff0c;在性能和结果上都是一样的。只有一些需要注意的事项 初始化列表一般情况如下&#xff1a; Date(int year, int …

设计模式---5(建造者模式的概念及其实现,建造者模式的角色与职责,建造者模式和工厂模式的区别)

建造者模式 建造者模式的概念 Builder 模式也叫建造者模式或者生成器模式&#xff0c;是由 GoF 提出的 23 种设计模式中的一种。 Builder 模式是一种对象创建型模式之一&#xff0c;用来隐藏复合对象的创建过程&#xff0c;它把复合对象的 创建过程加以抽象&#xff0c;通过子…

system阻塞SIGCHLD信号原因

system阻塞SIGCHLD信号原因 标签&#xff1a; c 2014-11-08 11:58 198人阅读 评论(0) 收藏 举报 分类&#xff1a; linux编程&#xff08;1&#xff09; 代码1&#xff1a;APUE10.18节的system函数源代码 int system(const char *cmdstring) /* with appropriate signal ha…

设计模式6---(单例模式的概念及其实现(懒汉式和饿汉式),线程安全)

单例模式 单例模式的概念 单例模式是一种对象创建型模式&#xff0c;使用单例模式&#xff0c;可以保证为一个类只生成唯一的实例对象。也就是说&#xff0c;在整个程序空间中&#xff0c;该类只存在一个实例对象。 GoF 对单例模式的定义是&#xff1a;保证一个类、只有一个实…

套接字编程---2(TCP套接字编程的流程,TCP套接字编程中的接口函数,TCP套接字的实现,TCP套接字出现的问题,TCP套接字多进程版本,TCP套接字多线程版本)

TCP模型创建流程图 TCP套接字编程中的接口 socket 函数 #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int socket(int domain, int type, int protocol); domain: AF_INET 这是大多数用来产生socket的协议&#xff0c;使用TCP或UDP来传输&…

Linux中netstat工具详解

简介 Netstat 命令用于显示各种网络相关信息&#xff0c;如网络连接&#xff0c;路由表&#xff0c;接口状态 (Interface Statistics)&#xff0c;masquerade 连接&#xff0c;多播成员 (Multicast Memberships) 等等。 常见参数 -a (all)显示所有选项&#xff0c;默认不显示…

网络基础 2-1(应用层,HTTP三点注意,HTTP协议格式, 最简单的HTTP服务器)

应用层 应用层 负责应用程序之间的数据沟通-----协议都是用户自己定的 自定制协议&#xff1a; 结构化数据传输 序列化&#xff1a; 将数据对象以指定的协议&#xff08;数据格式&#xff09;进行可用于持久化存储或者数据传输时的数据组织 例如在分布式的系统中&#xf…

网络基础2-2(传输层,端口,详谈UDP)

传输层 负责数据能够从发送端传输接收端. 端口号 端口号(Port)标识了一个主机上进行通信的不同的应用程序;在TCP/IP协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信(可以通过 netstat -n查看);一个端口只能被一个…

网络基础2-3(TCP协议,三次握手,四次挥手,TIME_WAIT状态的作用,TCP如何保证可靠传输,TCP连接中状态转化,滑动窗口,流量控制,快速重传,拥塞窗口,延迟应答,捎带应答,粘包问题)

TCP协议 TCP协议概念 TCP全称为 “传输控制协议(Transmission Control Protocol”). 人如其名, 要对数据的传输进行一个详细的控制 TCP协议格式 1. 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去; 2. 32位序号/32位确认号: 后面详细讲; 3. 4位TCP报头长度: 表示该…

字符串题目 1 --------判断两个字符串是否为旋转词

题目描述 如果一个字符串为str&#xff0c;把字符串的前面任意部分挪到后面形成的字符串交str的旋转词。比如str“12345”&#xff0c;str的旋转串有“12345”、“45123”等等。给定两个字符串&#xff0c;判断是否为旋转词。 输入描述: 输出包含三行&#xff0c;第一个两个…

字符串题目---2判断两个字符串是否为变形词

题目描述 给定两个字符串str1和str2&#xff0c;如果str1和str2中出现的字符种类出现的一样且每种字符出现的次数也一样&#xff0c;那么str1和str2互为变形词。请判断str1和str2是否为变形词 输入描述: 输入包括3行&#xff0c;第一行包含两个整数n&#xff0c;m(1 \leq n,…

设计模式7----代理模式

代理模式 概念 Proxy 模式又叫做代理模式&#xff0c;是结构型的设计模式之一&#xff0c;它可以为其他对象提供一 种代理&#xff08;Proxy&#xff09;以控制对这个对象的访问。 所谓代理&#xff0c;是指具有与代理元&#xff08;被代理的对象&#xff09;具有相同的接口的…

网络基础3-1(细谈IP协议头, 网络层,子网划分,路由选择,数据链路层,以太网帧格式,MAC地址,再谈ARP协议)

IP协议 IP协议头格式 4位版本号(version): 指定IP协议的版本, 对于IPv4来说, 就是44位头部长度(header length): IP头部的长度是多少个。32bit, 也就是 length * 4 的字节数. 4bit表示大 的数字是15, 因此IP头部大长度是60字节8位服务类型(Type Of Service): 3位优先权字段(已…

网络中典型协议--(DNS,输入url后, 发生的事情. ,ICMP,NAT)

DNS&#xff08;Domain Name System&#xff09; DNS是一整套从域名映射到IP的系统 域名服务器发展背景 TCP/IP中使用IP地址和端口号来确定网络上的一台主机的一个程序. 但是IP地址不方便记忆. 于是人们发明了一种叫主机名的东西, 是一个字符串, 并且使用hosts文件来描述主机…

高级IO--1 ---(五种典型IO,阻塞IO,非阻塞IO,信号驱动IO,异步IO, IO多路转接)

高级IO&#xff1a; 五种典型IO&#xff1a; 阻塞IO/非阻塞IO/信号驱动IO/异步IO/IO多路转接 IO多路转接模型&#xff1a;select/poll/epoll 五种典型IO 阻塞IO IO操作的流程&#xff1a;等待IO操作条件具备&#xff0c;然后进行数据拷贝 为了完成IO操作发起调用&#xff…

IO多路转接模型----(select的模型,select的优缺点,poll的模型,poll的优缺点)

IO多路转接模型&#xff1a;select/poll/epoll 对大量描述符进行事件监控(可读/可写/异常) select模型 用户定义描述符的事件监控集合 fd_set&#xff08;这是一个位图&#xff0c;用于存储要监控的描述符&#xff09;; 用户将需要监控的描述符添加到集合中&#xff0c;这个描…