线程应用(线程池)
线程池:
创建一堆工作线程(有最大数量限制),以及一个线程安全的队列,这些工作线程不断从任务队列取出任务进行处理
优点:
- 避免资源无限制使用所造成的资源耗尽的风险
- 避免频繁创建大量线程与销毁所带来的时间成本
实现:
- 直接在线程入口函数中定义好各种不同类型的处理方法
- 要处理什么数据,以及数据如何处理由外部传入
- 核心线程将需要处理的数据以及方法组织成一个任务,抛入线程池
线程池中的工作线程从任务队列中取出线程方法并处理数据
- 设计一个任务类(包含数据,以及处理方法,通过run接口,线程池中的线程获取节点后调用该接口就可以处理数据)run为公有接口封装私有成员函数
- 设计线程池类(线程(构造函数直接创建)+线程安全任务队列)
- 私有成员变量:最大线程数,最大队列节点数
- 创建线程入口函数entry,注意 entry作为入口函数参数仅有一个 ,如果在设计线程池类的过程中将其作为成员函数,存在隐含的this指针,导致入口函数的参数并非一个,不满足入口函数的定义
- 需要将入口函数entry设置为static成员函数,消除其中隐含的this指针,但此时又存在另外一个问题,导致入口函数无法访问私有成员变量(线程安全任务队列),此时在create线程时将this作为参数传入到入口函数中
- 线程池类定义任务入池操作,将每一个创建的任务节点放入线程池中,即线程池的任务安全队列中
- 每次调用任务,通过入口函数entry,将任务节点从线程池的队列中出队,然后调用run接口处理数据
- 在任务安全队列,取任务 放任务的过程需要加锁保护(BlockQueue),在调用run不需要加锁保护,因为取出不同的任务节点,调用不同的run接口,与其他线程不存在竞争
线程安全的单例设计模式:
应用场景:一个类只能实例化一个对象;一份资源只能被加载一次
实现:
- 饿汉模式:资源在程序初始化阶段就完成加载(空间换时间)
- 饿汉方法实现:
- 采用静态方法修饰资源,所有对象共用同一份资源,程序初始化阶段完成资源加载且只被加载一次
构造函数私有化 ,保证一个类只能实例化一个对象
template
class Singleton {static T data;
Singleton(){}//构造函数私有化
public:
static T* GetInstance() {
return &data;
}
};
- 懒汉模式:资源在使用的时候再去加载(延迟加载)
定义对象指针,初始资源为空
- static修饰,共用一份资源
- volatite修饰 ,防止编译器过度优化
- 加锁保护 线程安全
二次检测,防止锁冲突
template
class Singleton {volatite static T* inst;//定义对象指针 初始为空
static std::mutex _mutex;
public:
static T* GetInstance() {
if(inst==NULL)//double check 二次检测,避免不为空情况依然加锁,造成锁冲突
{
_mutex.lock();
if (inst == NULL) {
inst = new T();//调用时发现为空,进行获取资源
}
_mutex.unlock();
}
return inst;
}
};
注:STL容器 线程非安全
智能指针 线程安全
还没有评论,来说两句吧...