IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 线程池设计 从简单的我们平常设计线程池图解到生活中的类似线程池的处理现实场景 到简单的C++模拟nginx写的单链表组织工作队列的简单线程池实现 + nginx 部分源码刨析 -> 正文阅读

[系统运维]线程池设计 从简单的我们平常设计线程池图解到生活中的类似线程池的处理现实场景 到简单的C++模拟nginx写的单链表组织工作队列的简单线程池实现 + nginx 部分源码刨析

生活实例 整体 抽象 线程池, 其实线程池, 给我的感觉 核心 其实是 在于任务队列的设计上, 任务队列 + 互斥锁 + 条件变量 保证 任务队列的 中任务的有条不紊的 生产任务和 处理任务.........

这个池子: 其实 就是提前开启了 多个 死循环的处理任务的工作线程: 这些多个线程好比是现实生活中的办事窗口,任务队列就好比是我们去办事的人.....

看一张图: 人们排着队去 银行办事, 或者 医院挂号 办事:

其实这些? 窗口就是我们的工作线程: 他们其实是一开始就知道自己的办事流程的,,,,? ?一直死循环的等待工作,,,,,? ? ?是提前 开启的,,,? ?是 时刻准备着的,? 所以 是任务到来之前, 一创建线程池, 初始化线程池的时候, 就必须马上的启动这些工作线程......? ? ? ?(InitTreadPool就启动消费者线程)??

工作线程: 一般是 一直的 死循环的进行 等待 着 任务的到来 随时准备着 处理任务的........

任务队列:? 生产者, 不停的 生产存储着需要解决的任务......? ? (存在 异步解耦合性质?????).....

下面 先理解好啥叫作异步解耦?????? ??

队列。。。? 其实永远都是一个作用, 缓冲, 解除耦合性,,,,? ? 然后一提到 解耦合 永远都有一个叫做? ?异步解耦的说法, 但是? 这个概念总是非常的模糊的过去了。。。。。。。

异步解耦合: 就是两个事件之间是相互解除等待关系的,,,,,? (这个是我的简单的理解,如果有不对,欢迎各位给出改正, 我会非常表示感谢的,,,,,)

有了任务队列:? 其实 在所有线程都在繁忙的时候, 我们提供任务的线程需要不需要等待 线程空闲下来,我们把任务给到线程手上,我们才返回,,,,去收集其他任务提交信息呢????

答案当然是不需要,? 我们只是需要将任务给到任务队列中我们就不需要管了, 就可以直接返回了......? 这样我们就不受工作线程繁忙的影响了, 提供任务的线程将任务放到任务队列中,然后就可以去继续获取其他任务信息放入到任务队列中.......? ?

还可以用生活中的 快递驿站的例子理解

比如说常见的菜鸟驿站, 快递员们将 快递包裹(任务) 放入到菜鸟驿站就OK了......? ?然后快递员就可以离开去干其他事情了......

同样我们人去拿取快递, 也不需要和快递员直接交互, 我们也不是说快递员将快递放入到了菜鸟驿站,我们就需要立马去拿, 不需要, 我们可以先将手头上正在处理的事情处理好,然后 抽空去拿就OK了.....

如上就是我对于异步解耦的理解, 就是 生产者来说 我 不需要等着你可以消费了,我才生产, 我生产好了可以屯在队列中, 消费者 不是说你生产了我立马必须消费, 可以等到我自己可以消费了再消费,,, 异步性我感觉有一定的自由性....

线程池说了这么多理论, 相信大家都快烦了, 如果大家是学生的话就像快点来撸代码了,,,, 我学这里的时候完全是一个想法, 哈哈哈, 奉上大致的两份代码如下:? ? C++ 版本

首先写代码的时候? 需要了解一个点:? ? 线程处理函数的第一个参数需要是? void* 类型

?void *(*start_routine) (void *)? ?所以? 这个? Routine 线程执行的函数我们必须要 在类中进行一个static? 不然 第一个参数默认传入的是 this 指针, 这样会报错, 所以我们处理成static 函数,然后手动传入this指针实现

如下 首先是一个? thread_pool 的 代码:[tangyujie@VM-4-9-centos PthreadPool]$ cat pthread_pool.hpp

#pragma once
#include <iostream>
#include <queue>
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
using std::endl;
using std::cin;
using std::cout;
using std::queue;

template<class T>
class PthreadPool {
public:
????PthreadPool(int num = 3) :_num(num) {
????????pthread_mutex_init(&_lock, NULL);
????????pthread_cond_init(&_cond, NULL);
????}
????~PthreadPool() {
????????pthread_mutex_destroy(&_lock);
????????pthread_cond_destroy(&_cond);
????}
????void Lock() {
????????pthread_mutex_lock(&_lock);?????????????//上锁
????}
????void Unlock() {
????????pthread_mutex_unlock(&_lock);???????????//解锁
????}
????void WakeUp() {?????????????????????????????//唤醒进程, 通知消费者线程有任务了
????????pthread_cond_signal(&_cond);????????????//唤醒单个进程
????}
??void Wait() {?????????????????????????????????//没有任务, 消费者线程先阻塞起来等待任务?
????????pthread_cond_wait(&_cond, &_lock);? ? ? ??
????}
????bool IsEmptyQueue() {
????????return _taskqueue.empty();
????}
????static void* Routine(void* args) {? ? ? ? ??
????????PthreadPool* self = (PthreadPool*)args;???
????????while (1) {? ? ? ? ? ? ? ? ? ? ??
????????????self->Lock();???????????????????????????
????????????while (self->IsEmptyQueue()) {?????  //while ?防止伪唤醒,
????????????????//wait
????????????????self->Wait();
????????????}
????????????//说明存在 task了/
????????????T t;
????????????self->PopTask(t);
????????????self->Unlock();?????????????????????????
????????????t.Run();????????????????????????????//解锁后处理任务.... 做啥???
????????}
????}?
????void PushTask(const T& in) {????????????????//传入参数, push task
????????Lock();
????????_taskqueue.push(in);????????????????????//操作临界资源加锁
????????Unlock();
????????WakeUp();?????????????????????????????? ????????
????}
????void PopTask(T& out) {???????????????????????//传出参数 拿取任务
????????out = _taskqueue.front();????????????????//拿取pop任务
????????_taskqueue.pop();????????????????????????//任务队列pop 任务
????}
????void InitPthreadPool() {????????????????????   
????????pthread_t tid;????????
????????for (int i = 0; i < _num; ++i) {
????????????pthread_create(&tid, NULL, Routine, this);
????????????pthread_detach(tid);?????????????????//回收线程资源
????????}
????}
private:
????int _num;????????????????????????????????   //工作线程的数目
????queue<T> _taskqueue;????????                //任务队列
????pthread_mutex_t _lock;????????              //锁保证临界资源的互斥访问
????pthread_cond_t _cond;??????                 //条件变量控制资源到来时候的唤醒工作
};

然后是? task.hpp的代码 生产任务:#[tangyujie@VM-4-9-centos PthreadPool]$ cat task.hpp

#pragma once
#include <iostream>
#include <pthread.h>
using std::endl;
using std::cout;
using std::cerr;
//typedef int (*handler_t ) (int, int, char);

class Task {
public:
?? ?Task(int x = 1, int y = 1, char op = '+')?? ??? ??? ??? ?//默认构造?
?? ??? ?: _x(x)
?? ??? ?, _y(y)
?? ??? ?, _op(op) ?
?? ?{}
?? ?~Task(){}
?? ?void Run() {
?? ??? ?int z = 0;
?? ??? ?switch(_op) {
?? ??? ??? ?case '+':
?? ??? ??? ??? ?z = _x + _y;
?? ??? ??? ??? ?break;
?? ??? ??? ?case '-':
?? ??? ??? ??? ?z = _x - _y;
?? ??? ??? ??? ?break;
?? ??? ??? ?case '*':
?? ??? ??? ??? ?z = _x * _y;
?? ??? ??? ? ? ?break;
?? ??? ??? ?case '/':
?? ??? ??? ??? ?if (_y == 0) {cerr << "div zero!" << endl; break;}
?? ??? ??? ??? ?z = _x / _y;
?? ??? ??? ??? ?break;
?? ??? ??? ?case '%':
?? ??? ??? ??? ?if (_y == 0) {cerr << "mod zero!" << endl; break;}
?? ??? ??? ??? ?z = _x % _y;
?? ??? ??? ??? ?break;
?? ??? ??? ?default:
?? ??? ??? ??? ?cerr << "operator error!" << endl;
?? ??? ??? ??? ?break;
?? ??? ?}?
?? ??? ?cout << "thread: [" << pthread_self() << "]: "<< _x << _op << _y << "=" << z << endl;?
?? ?}
private:
?? ?int _x;
?? ?int _y;
?? ?char _op;
};

最后一个是 测试函数? main.cc的代码:[tangyujie@VM-4-9-centos PthreadPool]$ cat main.cc

#include "task.hpp"
#include "pthread_pool.hpp"
#include <cstdlib>
#include <ctime>

int main() {
?? ?PthreadPool<Task> * tp = new PthreadPool<Task>();
?? ?tp->InitPthreadPool();
?? ?srand((unsigned long)time(nullptr));
?? ?const char* ops = "+-*/%";
?? ?while (1) {
?? ??? ?int x = rand() % 123 + 1;
?? ??? ?int y = rand() % 123 + 1;
?? ??? ?Task t(x, y, ops[rand() % 5]);
?? ??? ?tp->PushTask(t);
? ? sleep(1);
?? ?}
?? ?return 0;
}

?至此: 基本对于线程池基本上是知道理论了:?

?然后如下 介绍一下? 线程池? 为啥好??????池化技术有啥好处????

首先:? 线程池, 池子,? 对于池子, 我的印象就是蓄水池了, 比如说在缺水的底带, 家里要大水如果需要到很远的地方去打水的化, 还有需要水的时候才接水.... 可以吗???? 当然可以, 但是这样需要的时候立马打水? 或者到远处去运输水? 对于这个时间的消耗是不是很大, 要是 我们提前造一个池子, 需要的话直接去池子里面去拿取, 是不是效率会高很多.............

内存池, 线程池? 其实都是常见的池化技术,? ?线程池, 避免了临时创建大量线程, 充分的实现了线程的复用, 我们可以反复利用我们最初线程池初始创建的时候就创建好的多线程? ? ?(工作线程)

自此:? 算是暂时小结了, 写了太多了,,,, 其中都是鄙人的拙见, 如果觉得有帮助希望点个赞,欢迎评论, 最后 好了啦, 不卷了, 大家新年快乐, 学完收工.... 至于??nginx 部分源码刨析留着下次写吧

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-01-30 19:17:57  更:2022-01-30 19:18:06 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/16 7:24:00-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码