moduo之线程池ThreadPool

server/2024/11/25 11:55:05/

简介

moduo实现了通用业务线程池,其任务使用无参的函数对象,其任务队列使用的是有界的队列

结构

1
0..n
ThreadPool
- MutexLock mutex_
- Condition notEmpty_
- Condition notFull_
- deque<Task> queue_
- size_t maxQueueSize_
- string name_
- Task threadInitCallback_
- bool running_
- vector<ThreadPtr> threads_
-bool isFull()
-void runInThread()
-Task take()
+void setMaxQueueSize(int maxSize)
+void setThreadInitCallback(const Task& cb)
+const string& name()
+size_t queueSize()
+void start(int numThreads)
+void stop()
+void run(Task f)
Thread
- bool started_
- bool joined_
- pthread_t pthreadId_
- pid_t tid_
- ThreadFunc func_
- string name_
- CountDownLatch latch_
- static AtomicInt32 numCreated_
-void setDefaultName()
+void start()
+int join()
+bool started()
+pid_t tid()
+const string& name()
+static int numCreated()

线程池

线程池属性

有线程池名name_,任务队列的最大数maxQueueSize_,线程池的运行状态running_,工作线程启动时的初始化函数threadInitCallback_

void setMaxQueueSize(int maxSize) 
{ maxQueueSize_ = maxSize; 
}void setThreadInitCallback(const Task& cb)
{ threadInitCallback_ = cb; 
}ThreadPool::ThreadPool(const string& nameArg): mutex_(),notEmpty_(mutex_),notFull_(mutex_),name_(nameArg),maxQueueSize_(0),running_(false)
{
}const string& name() const{ return name_; }

线程池的开启和结束

开启是start,结束是stop,向任务队列中提交任务是run
start设置线程池的运行状态running_ 为true,调整线程池的容量,并且创建指定numThreads个线程,工作线程的执行函数为runInThread,工作线程先执行线程初始化函数,然后从任务队列中取出任务执行

void ThreadPool::start(int numThreads)
{running_ = true;threads_.reserve(numThreads);for (int i = 0; i < numThreads; ++i){char id[32];snprintf(id, sizeof id, "%d", i+1);threads_.emplace_back(new muduo::Thread(std::bind(&ThreadPool::runInThread, this), name_+id));threads_[i]->start();}if (numThreads == 0 && threadInitCallback_){threadInitCallback_();}
}void ThreadPool::runInThread()
{try{if (threadInitCallback_){threadInitCallback_();}while (running_){Task task(take());if (task){task();}}}catch (const Exception& ex){fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());fprintf(stderr, "reason: %s\n", ex.what());fprintf(stderr, "stack trace: %s\n", ex.stackTrace());abort();}catch (const std::exception& ex){fprintf(stderr, "exception caught in ThreadPool %s\n", name_.c_str());fprintf(stderr, "reason: %s\n", ex.what());abort();}catch (...){fprintf(stderr, "unknown exception caught in ThreadPool %s\n", name_.c_str());throw; // rethrow}
}ThreadPool::Task ThreadPool::take()
{MutexLockGuard lock(mutex_);// always use a while-loop, due to spurious wakeupwhile (queue_.empty() && running_){notEmpty_.wait();}Task task;if (!queue_.empty()){task = queue_.front();queue_.pop_front();if (maxQueueSize_ > 0){notFull_.notify();}}return task;
}

stop设置线程池运行状态为false,同时唤醒队列的两个条件变量,等待所有工作线程执行完成

void ThreadPool::stop()
{{MutexLockGuard lock(mutex_);running_ = false;notEmpty_.notifyAll();notFull_.notifyAll();}for (auto& thr : threads_){thr->join();}
}

run提交任务到工作队列中,如果队列满则等待直到队列有空闲空间,将任务放入工作队列后,唤醒工作线程

void ThreadPool::run(Task task)
{if (threads_.empty()){task();}else{MutexLockGuard lock(mutex_);while (isFull() && running_){notFull_.wait();}if (!running_) return;assert(!isFull());queue_.push_back(std::move(task));notEmpty_.notify();}
}

线程

线程初始化

设置状态变量,线程执行函数,线程默认名,默认是Thread+numCreated_

Thread::Thread(ThreadFunc func, const string& n): started_(false),joined_(false),pthreadId_(0),tid_(0),func_(std::move(func)),name_(n),latch_(1)
{setDefaultName();
}void Thread::setDefaultName()
{int num = numCreated_.incrementAndGet();if (name_.empty()){char buf[32];snprintf(buf, sizeof buf, "Thread%d", num);name_ = buf;}
}

线程启动

ThreadData作为线程数据传到创建线程时的参数中,主要包含线程执行函数,线程名,线程id以及创建线程与线程执行同步变量
启动线程的函数为startThread,其会调用ThreadDatarunInThread
start启动线程,修改线程状态started_为true,通过latch_等待线程启动完成

void Thread::start()
{assert(!started_);started_ = true;// FIXME: move(func_)detail::ThreadData* data = new detail::ThreadData(func_, name_, &tid_, &latch_);if (pthread_create(&pthreadId_, NULL, &detail::startThread, data)){started_ = false;delete data; // or no delete?LOG_SYSFATAL << "Failed in pthread_create";}else{latch_.wait();assert(tid_ > 0);}
}void* startThread(void* obj)
{ThreadData* data = static_cast<ThreadData*>(obj);data->runInThread();delete data;return NULL;
}struct ThreadData
{typedef muduo::Thread::ThreadFunc ThreadFunc;ThreadFunc func_;string name_;pid_t* tid_;CountDownLatch* latch_;ThreadData(ThreadFunc func,const string& name,pid_t* tid,CountDownLatch* latch): func_(std::move(func)),name_(name),tid_(tid),latch_(latch){ }void runInThread(){*tid_ = muduo::CurrentThread::tid();tid_ = NULL;latch_->countDown();latch_ = NULL;muduo::CurrentThread::t_threadName = name_.empty() ? "muduoThread" : name_.c_str();::prctl(PR_SET_NAME, muduo::CurrentThread::t_threadName);try{func_();muduo::CurrentThread::t_threadName = "finished";}catch (const Exception& ex){muduo::CurrentThread::t_threadName = "crashed";fprintf(stderr, "exception caught in Thread %s\n", name_.c_str());fprintf(stderr, "reason: %s\n", ex.what());fprintf(stderr, "stack trace: %s\n", ex.stackTrace());abort();}catch (const std::exception& ex){muduo::CurrentThread::t_threadName = "crashed";fprintf(stderr, "exception caught in Thread %s\n", name_.c_str());fprintf(stderr, "reason: %s\n", ex.what());abort();}catch (...){muduo::CurrentThread::t_threadName = "crashed";fprintf(stderr, "unknown exception caught in Thread %s\n", name_.c_str());throw; // rethrow}}
};

线程结束

在线程启动后,没有调用join默认是分离的线程
join等待线程执行结束

Thread::~Thread()
{if (started_ && !joined_){pthread_detach(pthreadId_);}
}int Thread::join()
{assert(started_);assert(!joined_);joined_ = true;return pthread_join(pthreadId_, NULL);
}

线程属性

线程运行状态started_,线程idtid_,线程名name_

bool started() const 
{ return started_; 
}pid_t tid() const 
{ return tid_; 
}const string& name() const 
{ return name_; 
}

http://www.ppmy.cn/server/144785.html

相关文章

yolo算法详解

作为一名计算机专业的专家,我对YOLO(You Only Look Once)算法有着深入的了解。以下是对YOLO的详细介绍: 一、基本概念YOLO是一种流行的目标检测算法,它基于卷积神经网络(CNN)进行目标检测任务。与传统的目标检测算法(如R-CNN系列)不同,YOLO的核心思想是将目标检测问题…

Figma入门-基本操作制作登录页

Figma入门-基本操作制作登录页 前言 在之前的工作中&#xff0c;大家的原型图都是使用 Axure 制作的&#xff0c;印象中 Figma 一直是个专业设计软件。 最近&#xff0c;很多产品朋友告诉我&#xff0c;很多原型图都开始用Figma制作了&#xff0c;并且很多组件都是内置的&am…

241124学习日志——[CSDIY] [ByteDance] 后端训练营 [14]

CSDIY&#xff1a;这是一个非科班学生的努力之路&#xff0c;从今天开始这个系列会长期更新&#xff0c;&#xff08;最好做到日更&#xff09;&#xff0c;我会慢慢把自己目前对CS的努力逐一上传&#xff0c;帮助那些和我一样有着梦想的玩家取得胜利&#xff01;&#xff01;&…

【创建型设计模式】工厂模式

【创建型设计模式】工厂模式 创建型设计模式第二期&#xff01;本期介绍简单工厂模式和工厂方法模式。 简单工厂模式 简单工厂模式&#xff08;又叫作静态工厂方法模式&#xff09;&#xff0c;其属于创建型设计模式&#xff0c;简单工厂模式不属于设计模式中的 23 种经典模…

2024最新YT-DLP使用demo网页端渲染

2024最新YT-DLP使用demo网页端渲染 前提摘要1.使用python的fastapi库和jinjia2库进行前端渲染2.代码实现1&#xff09;目录结构2&#xff09;代码style.cssindex.htmlresult.htmlmain.pyrun.py 3&#xff09;运行测试命令端运行 3.项目下载地址 前提摘要 2024最新python使用yt…

Epipolar-Free 3D Gaussian Splatting for Generalizable Novel View Synthesis 论文解读

目录 一、概述 二、相关工作 1、单场景3DGS 2、跨场景生成3DGS 3、几何方法解决3D任务 三、eFreeSplat 1、预训练跨视角模块 2、无外极线跨视角交互感知模块 3、迭代跨视角高斯对齐 4、高斯参数预测 一、概述 该论文设计了一种不依赖于极线约束的情况实现可推广的新视…

Spring AI Fluent API:与AI模型通信的流畅体验

引言 随着人工智能&#xff08;AI&#xff09;技术的飞速发展&#xff0c;越来越多的应用场景开始融入AI技术以提升用户体验和系统效率。在Java开发中&#xff0c;与AI模型通信成为了一个重要而常见的需求。为了满足这一需求&#xff0c;Spring AI引入了ChatClient&#xff0c…

书生浦语实战训练营L1G5000

XTuner 微调个人小助手认知任务 记录复现过程并截图。 基础任务&#xff08;完成此任务即完成闯关并获得 100 算力点&#xff09; 使用 XTuner 微调 InternLM2-Chat-7B 实现自己的小助手认知&#xff0c;如下图所示&#xff08;图中的尖米需替换成自己的昵称&#xff09;&…