欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

多线程应用

时间:2023-08-03
线程池

一堆线程进行任务处理,主要针对大量任务需要处理的场景,使用多执行流可以提高处理效率

如果一个任务到来就创建一个线程来处理这有很大缺点:

成本:总耗时=线程创建时间+任务处理时间+线程销毁时间,如果任务处理时间短,则大量时间被线程创建与销毁消耗了风险:如果有大量线程进来,则在峰值压力下系统可能会有崩溃风险

思想:线程池其实是一堆创建好的线程和一个任务队列,有任务来了就抛入线程池中,分配一个线程进行处理

线程池中的线程与任务节点数量都有最大限制,避免资源消耗.

实现:

typedef void (*handler_t)(int data);class ThreadTask{ private: int _data;//要处理的数据 handler_t _handler;//处理数据的函数 public: ThreadTask() {} ThreadTask(int data, handler_t handler):_data(data), _handler(handler){} void Run(){ _handler(_data); }};class BlockQueue{ private: std::queue _queue; int _capacity; pthread_mutex_t _mutex; pthread_cond_t _cond_pro; pthread_cond_t _cond_con; public: BlockQueue(int maxq = MAXQ):_capacity(maxq){ pthread_mutex_init(&_mutex, NULL); pthread_cond_init(&_cond_pro, NULL); pthread_cond_init(&_cond_con, NULL); } ~BlockQueue() { pthread_mutex_destroy(&_mutex); pthread_cond_destroy(&_cond_pro); pthread_cond_destroy(&_cond_con); } bool Push(const ThreadTask &data){ pthread_mutex_lock(&_mutex); while(_queue.size() == _capacity) { pthread_cond_wait(&_cond_pro, &_mutex); } _queue.push(data); pthread_mutex_unlock(&_mutex); pthread_cond_signal(&_cond_con); return true; } bool Pop(ThreadTask *data) { pthread_mutex_lock(&_mutex); while(_queue.empty() == true) { pthread_cond_wait(&_cond_con, &_mutex); } *data = _queue.front(); _queue.pop(); pthread_mutex_unlock(&_mutex); pthread_cond_signal(&_cond_pro); return true; }};class Threadpool{ private: int _max_thread;//线程最大数量 int _max_queue;//任务队列中节点最大数量 BlockQueue _queue; public: Threadpool(int max_thr=MAX_THREAD, int max_q=MAXQ): _max_thread(max_thr), _max_queue(max_q), _queue(max_q){ pthread_t tid; int ret; for (int i = 0; i < max_thr; i++) { ret = pthread_create(&tid, NULL, thr_entry, this); if (ret != 0) { printf("thread create errorn"); exit(-1); } pthread_detach(tid); } } static void *thr_entry(void *arg){ Threadpool *pool = (Threadpool*)arg; while(1) { ThreadTask task; pool->_queue.Pop(&task); task.Run(); } } bool TaskPush(const ThreadTask &task) { _queue.Push(task); }};

单例模式

针对场景:一个类只能实例化一个对象,提供一个访问接口,也就是说一个资源在内存中只能有一份

目的:节约内存;防止数据二义;

具体实现

饿汉与懒汉模式

饿汉资源全部提前加载初始化完毕,用的时候直接用(以空间换时间)

构造函数私有化,无法在类外实例化对象在类内实例化全局唯一对象,资源单独一份共享,运行前初始化,初始化过程不用考虑线程安全问题

懒汉:资源使用的时候再加载(用的比较多)

构造函数私有在访问接口中加锁保护资源初始化加载过程二次检测,防止锁冲突,提高效率防止编译器过度优化,使用volatile修饰指针成员变量

//饿汉模式class Singleton{ public: static Singleton* GetInstance() { return &_instance; } private: Singleton(){}; Singleton(Singleton const&); static Singleton _instance;//全局的唯一对象};

//懒汉模式class Singleton{public: volatile static Singleton* GetInstance() { if (_instance == nullptr) { m_mutex.lock(); if (_instance == nullptr) { _instance = new Singleton(); } m_mutex.unlock(); } return _instance; }private: Singleton() {};//构造函数私有 volatile static Singleton* _instance;//单例对象指针 static mutex m_mutex;//互斥锁};

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。