1. 单线程和多线程?
单线程:只是一条线程在执行任务。
多线程:创建多条线程同时执行一个任务。
并行:多个程序分别在不同的CPU处理机上运行,不抢占资源且可以同时运行。
并发:在一个时间段内,多个程序都启动运行在同一个处理机上。
1.1 多线程的优点
- 更加高效的内存共享,多进程下内存共享不方便
- 较轻的上下文切换,因为不用切换地址空间。
1.2 多进程的优点
- 各个进程之间有自己独立的内存空间,所以有更强的容错性,不至于一个集成crash崩溃导致系统崩溃。
- 具有更好的可伸缩性,因为进程将地址空间、页表等进行了隔离,在多核上可伸缩性更强。
1.3 如何提升多线程的效率
- 尽量使用线程池,从而不用频繁的创建、销毁线程。
- 减少线程之间的同步和通信。
- 避免产生大量缺页异常。
- 避免需要频繁共享写的数据。
多线程安全问题,请参考:https://editor.csdn.net/md/?articleId=108306065
2. 线程池
在一个应用程序中,需要多次使用线程,也就意味着,我们需要多次创建并销毁线程。而创建并销毁线程的过程势必会消耗内存。所以提出了线程池的概念。
2.1 什么是线程池:
一种线程使用模式。在任务处理中,提前创建固定量的线程,循环去处理任务。
2.2 应用场景:
需要大量的线程来完成任务,并且完成任务的时间比较短。
2.3 优点:
- 避免针对每个请求都创建线程资源耗尽的风险。
- 避免大量频繁的创建、销毁所带来的时间成本。
3. 线程池的创建
- 创建固定量的线程池,循环从任务队列中获取任务对象。
- 获取到任务对象后,执行任务对象中的任务接口
- 设计一个任务队列的类
typedef void(*handler_t)(int data);//定义函数指针类型
class ThreadTask
{
private:
int _data;//线程池中要处理的数据
handler_t _handler;//线程池中要执行的处理函数,使用这个函数处理数据
public:
void SetTask(int data, handler_t handler)
{//传入数据与处理 函数,设置任务
_data = data;
_handler = handler;
}
void Run()
{//提供公有接口调用能够完成任务处理
return _handler(_data);
}
}
- 设计线程池类
class ThreadPool
{
private:
int _thread_max;//线程池中线程的最大数量,初始化创建这么多个线程
void *thread_start(void *arg);//线程入口函数,不断循环从队列中取出任务,执行Run完成任务处理
std::queue<ThreadTask> _queue;
int _capacity;
pthread_mutex_t _mutex;
pthread_cond_t _cond_push;
pthread_cond_t _cond_pop;
public:
bool PushTask(ThreadTask &tt);//任务入队函数
}