线程池linux Linux下线程池(ThreadPool)
发布时间:2022-10-21 12:51:27 所属栏目:Linux 来源:
导读: 目次
一.线程池干系概念及其优点
线程池一种线程使用模式,线程过多会带来这个调治的开销进而影响团体的性能,而线程池是提前准备好了线程期待着管理者举行分配使命。
1.线程池的优点告
一.线程池干系概念及其优点
线程池一种线程使用模式,线程过多会带来这个调治的开销进而影响团体的性能,而线程池是提前准备好了线程期待着管理者举行分配使命。
1.线程池的优点告
|
目次 一.线程池干系概念及其优点 线程池一种线程使用模式,线程过多会带来这个调治的开销进而影响团体的性能,而线程池是提前准备好了线程期待着管理者举行分配使命。 1.线程池的优点告急有一下几个方面: 2.线程池的应用场景: 二.线程池的实现 再这里实现的是一个简朴的线程池,再这个线程池当中有一个使命队列,线程从使命队列当中提前使命,已经多少个线程,一开始再特点的条件变量下举行期待。使命队列是范例的生产者-消耗者模子线程池linux,本模子至少必要两个工具:一个 mutex + 一个条件变量,或是一个 mutex + 一个信号量。mutex 现实上就是锁,包管使命的添加和移除(获取)的互斥性,一个条件变量是包管获取 task 的同步性:一个 empty 的队列,线程应该期待(壅闭)。 对应线程池的实现 #pragma once #include "Task.hpp" #include #include #include #define NUM 5 template class ThreadPool { private: ??void LockQueue() ??{ ? ? pthread_mutex_lock(&_mtx); ??} ??void UnlockQueue() ??{ ? ? pthread_mutex_unlock(&_mtx); ??} ??void Wait() ??{ ? ? pthread_cond_wait(&_cond, &_mtx); ??} ??void WakeUp() ??{ ? ? pthread_cond_signal(&_cond); ??} ??bool IsEmpty() ??{ ? ? return _task_queue.size() == 0; ??} public: ??static void *Routine(void *arg)//为什么必须是static方法在博客中细说 ??{ ? ? auto *self = (ThreadPool *)arg; ? ? pthread_detach(pthread_self());//分离线程 ? ? while (true) ? ? { ? ?? ?self->LockQueue(); ? ?? ?while (self->IsEmpty())//看此时的任务队列当中是否有任务 ? ?? ?{ ? ?? ???self->Wait(); ? ?? ?} ? ?? ?T task; ? ?? ?self->pop(&task); ? ?? ?self->UnlockQueue(); ? ?? ?task.Run();//处理任务 ? ? } ??} ??void Push(const T &val) ??{ ? ? LockQueue(); ? ? _task_queue.push(val); ? ? UnlockQueue(); ? ? WakeUp();//唤醒在条件变量下等待的一个线程 ??} ??void pop(T *out) ??{ ? ? *out = _task_queue.front(); ? ? _task_queue.pop(); ??} ??void InitThreadPool() ??{ ? ? //初始化线程池并创建线程 ? ? pthread_t tid; ? ? for (int i = 0; i < _num; i++) ? ? { ? ?? ?pthread_create(&tid, NULL, Routine, this); ? ? } ??} ??//销毁信号量 ??~ThreadPool() ??{ ? ? pthread_mutex_destroy(&_mtx); ? ? pthread_cond_destroy(&_cond); ??} ??//获取单例 ??static ThreadPool *GetInstance() ??{ ? ? static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; ? ? if (NULL == tp) ? ? { ? ?? ?pthread_mutex_lock(&mtx);//多个线程可能同时进来 ? ?? ?if (NULL == tp) ? ?? ?{ ? ?? ???tp = new ThreadPool(); ? ?? ?} ? ?? ?pthread_mutex_unlock(&mtx); ? ? } ? ? return tp; ??} private: ??ThreadPool(int num = NUM) : _num(num) ??{ ? ? pthread_mutex_init(&_mtx, NULL); ? ? pthread_cond_init(&_cond, NULL); ??} ??//禁掉拷贝构造和赋值 ??ThreadPool(const ThreadPool&tp)=delete; ??ThreadPool&operator=(const ThreadPool&tp)=delete; ??static ThreadPool *tp; ??pthread_mutex_t _mtx; ??pthread_cond_t _cond; ??int _num;//线程的数量 ??std::queue _task_queue;//任务队列 }; template ThreadPool *ThreadPool::tp = NULL; 复制代码 代码表明: 在这里必要条件变量和互斥锁的缘故原由是:多个线程大概同时访问使命队列,此时这个使命队列就变成了临界资源,锁以我们必要引入互斥锁来掩护临界资源。线程池中的线程去这个使命队列当中拿使命的条件必须是使命队列当中要有使命,假如此时我们只使用互斥锁那么就有大概出现互斥锁不停被一个线程占用着,这是不公道的因此我们必要引入条件变量。当外部向使命队列当中放入使命之后,必要唤醒在条件变量劣期待的线程。在这里特殊必要注意的有一下几点: 大概信心的老铁会发现为什么线程实行的方法是静态的? 我们在学习C++的时间我们知道非静态的成员函数默认会转达this指针,而且是第一个参数这就和我们线程库的参数情势辩说了以是我们必要将其设置为静态的函数。但是这也引发了别的一个题目线程在实行Routine函数时无法调用其他的成员函数,静态的成员函数是属于整个类的而不是属于某个对象,以是了我们必要将this作为参数体现的传进去如许我们就可以在这个静态的成员函数类调用其他函数了 使命类 在这里我们线程池处置惩罚的使命,我们将其封装成一个类,这个类提供一个Run方法用于实行使命在这里为了简朴只是简朴的设置成为一个盘算使命类: [code]#include //使命类class Task{public: Task(int x = 0, int y = 0, char op = 0) : _x(x), _y(y), _op(op) {} ~Task() {} //处置惩罚使命的方法 void Run() { int result = 0; switch (_op) { case '+': result = _x + _y; break; case '-': result = _x - _y; break; case '*': result = _x * _y; break; case '/': if (_y == 0){ std::cerr (编辑:财气旺网 - 财气网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
站长推荐

