线程池~~

目录

一丶什么是线程池

 二丶线程池的优点

 三丶线程池的应用

四丶线程池种类

五丶线程池使用

 六丶单例模式

1.饿汉模式

2.懒汉模式

 3.单例模式线程池(懒汉模式)


一丶什么是线程池

        线程池是线程的一种使用模式。在前面的情况中,我们都是遇到任务然后创建线程再执行。但是线程的频繁创建就类似于内存的频繁申请,会给操作系统带来更大的压力,进而影响整体的性能。

        所以我们一次申请好一定数量而定线程,然后将线程的管理操作交给线程池,就避免了在短时间内不断创建与销毁线程的代价,线程池不但能够保证内核的充分利用,还能防止过分调度,并根据实际业务情况进行修改。

 二丶线程池的优点

  1. 任务来到立马就有线程去执行任务,节省了创建线程的时间。
  2. 防止服务器线程过多导致的系统过载问题
  3. 相对于进程池,线程池资源占用较少,但是健壮性很差 

 三丶线程池的应用

  1.         需要大量的线程来完成任务,且完成任务的时间比较短。 WEB服务器完成网页请求这样的任务,使用线程池技 术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。 但对于长时间的任务,比如一个 Telnet连接请求,线程池的优点就不明显了。因为Telnet会话时间比线程的创建时间大多了。
  2.         对性能要求苛刻的应用,比如要求服务器迅速响应客户请求。
  3.         接受突发性的大量请求,但不至于使服务器因此产生大量线程的应用。突发性大量客户请求,在没有线程池情 况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程可能使内存到达极限, 出现错误.

四丶线程池种类

  1.  创建固定数量线程池,循环从任务队列中获取任务对象
  2.  获取到任务对象后,执行任务对象中的任务接口

五丶线程池使用

 pthreadpool.hpp

#include<iostream>
#include<pthread.h>
#include<queue>
#include"task.hpp"
#include<unistd.h>
using namespace std;
using namespace qzh1;



namespace qzh    
{    
    const int g_num = 5;    
    template <class T>    
    class ThreadPool    
    {    
    private:    
        int num_; //固定大小的线程池   
        queue<T> task_queue_; //任务队列,使用STL的queue实现   
        pthread_mutex_t mtx_; //定义一把锁  
        pthread_cond_t cond_; //定义一个条件变量
   
    public:    
        void Lock() { pthread_mutex_lock(&mtx_);} //加锁操作     
    
        void Unlock() { pthread_mutex_unlock(&mtx_);} //解锁操作   
   
        bool IsEmpety() { return task_queue_.empty();} //判断任务队列是否为空  
    
        void Wait() { pthread_cond_wait(&cond_, &mtx_);} //让线程在条件变量下等待   
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
        void WakeUp() { pthread_cond_signal(&cond_);} //唤醒在条件变量下等待的线程   
   
    public:    
        ThreadPool(int num = g_num):num_(num)    
        {    
            pthread_mutex_init(&mtx_, nullptr);    
            pthread_cond_init(&cond_, nullptr);    
        }    
    
        //在类中要让线程执行类内成员方法,是不可行的    
        //必须让线程执行静态方法    
        static void* Rountine(void* args)    
        {    
            pthread_detach(pthread_self());    
            ThreadPool<T>* tp = (ThreadPool<T>*)args;    
            while(true)    
            {    
                tp->Lock();    
                while(tp->IsEmpety())    
                {    
                    tp->Wait();    
                }    
                T t;    
                tp->PopTask(&t);    
                tp->Unlock();    
                t.Run();    
    
            }    
        }    
    
        void InitThreadPool()    
        {    
            pthread_t tid;    
            for(int i = 0; i < num_; i++)    
            {    
                pthread_create(&tid, nullptr, Rountine, (void*)this);    
            }    
        }    
    
        void PushTask(const T& in)//向任务队列添加任务    
        {    
            Lock();    
            task_queue_.push(in);    
            Unlock();    
            WakeUp();    
        }    
    
        void PopTask(T* out)//从任务队列获取任务    
        {    
            *out = task_queue_.front();    
            task_queue_.pop();    
        }    
    
        ~ThreadPool()    
        {    
            pthread_mutex_destroy(&mtx_);    
            pthread_cond_destroy(&cond_);    
        }    
    };    
}

main.cc

#include "threadpool.hpp"
#include "task.hpp"
#include <ctime>    
#include <cstdlib>

using namespace qzh;
using namespace qzh1;





int main()                                                                                                                                                                            
{    
    ThreadPool<Task>* tp = new ThreadPool<Task>();//创建线程池    
    tp->InitThreadPool();  //进行初始化  
    srand((long long)time(nullptr));//生产随机数    
    while(true) //不断向任务队列塞数据   
    {    
        Task t(rand() % 20 + 1, rand() % 10 + 1, "+-*/%"[rand() % 5]);    
        tp->PushTask(t);    
        sleep(1);    
    }    
    return 0;    
}

task.hpp

#pragma once                                                                                                                                                                                                                                                                                                                                                                
#include <iostream>    
#include <pthread.h>    
using namespace std;    
    
namespace qzh1    
{    
    class Task    
    {    
    private:    
        int x_;    
        int y_;    
        char op_;//用来表示:+ 、- 、* 、/ 、%    
    public:    
        Task(){}    
        Task(int x, int y, char op):x_(x), y_(y), op_(op){}    
    
        string show()    
        {    
            string message = to_string(x_);    
            message += op_;    
            message += to_string(y_);    
            message += "=?";    
            return message;    
        }    
        int Run()    
        {    
            int res = 0;    
            switch(op_)    
            {    
                case '+':    
                  res = x_ + y_;    
                  break;    
                case '-':    
                  res = x_ - y_;    
                  break;    
                case '*':    
                  res = x_ * y_;    
                  break;    
                case '/':    
                  res = x_ / y_;    
                  break;    
                case '%':    
                  res = x_ % y_;    
                  break;    
                default:    
                  cout << "bug" << endl;    
                  break;    
            }    
            printf("当前任务正在被:%lu处理,处理结果为:%d %c %d = %d\n",pthread_self(), x_, op_, y_, res);     
            return res;    
        }    
    
        int operator()()    
        {    
            return Run();    
        }    
    
        ~Task(){}    
    };    
}

 六丶单例模式

        单例(Singleton)模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例 ;

使用场景:

        语义上只需要一个
        该对象内部存在大量的空间,保存了大量的数据,如果允许该对象存在多份,或者允许发生各种拷贝,内存中存在冗余数据;
一般Singleton模式通常有三种形式:

        饿汉式:吃完饭, 立刻洗碗, 这种就是饿汉方式. 因为下一顿吃的时候可以立刻拿着碗就能吃饭。
        懒汉式:吃完饭, 先把碗放下, 然后下一顿饭用到这个碗了再洗碗, 就是懒汉方式。
        懒汉方式最核心的思想是 "延时加载"。(例如我们之前所学过的写时拷贝)从而能够优化服务器的启动速度。

1.饿汉模式

类在被加载的时候会实例化一个对象 

template <typename T> 
class Singleton 
{ 
private:
    static Singleton<T> data;//饿汉模式,在加载的时候对象就已经存在了 
public: 
    static Singleton<T>* GetInstance() 
    { 
        return &data; 
    } 
};

2.懒汉模式


template <typename T> 
class Singleton 
{ 
private:
    static Singleton<T>* inst; //懒汉式单例,只有在调用GetInstance时才会实例化一个单例对象
public: 
    static Singleton<T>* GetInstance() 
    { 
        if (inst == NULL) 
        { 
            inst = new Singleton<T>(); 
        }
    return inst; 
    } 
};

 3.单例模式线程池(懒汉模式)

threadpool.hpp

#include <iostream>
#include <pthread.h>
#include <ctime>
#include <cstdlib>
#include <unistd.h>
#include <queue>
using namespace std;
namespace qzh
{
    const int max = 5;
    template <class T>
    class Pthreadpool
    {
    private:
        int _cap;
        queue<T> _taskque;
        pthread_mutex_t _mtx;
        pthread_cond_t _cod;
        static Pthreadpool<T> *ins;

    private:
        Pthreadpool(int cap = max) : _cap(cap)
        {
            pthread_mutex_init(&_mtx, nullptr);
            pthread_cond_init(&_cod, nullptr);
        }
        Pthreadpool(const Pthreadpool<T> &tp) = delete;
        Pthreadpool<T> &operator=(Pthreadpool<T> &tp) = delete;

    public:
        static Pthreadpool<T> *GetInstance()
        {
            static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
            if (ins == nullptr)
            {
                pthread_mutex_lock(&lock);
                if (ins == nullptr)
                {
                    ins = new Pthreadpool<T>();
                    cout << "首次加载对象" << endl;
                    ins->InitPool();
                }
                pthread_mutex_unlock(&lock);
            }
            return ins;
        }
        void Lock()
        {
            pthread_mutex_lock(&_mtx);
        }
        void Unlock()
        {
            pthread_mutex_unlock(&_mtx);
        }
        bool Isempty()
        {
            return _taskque.empty();
        }
        void Wait()
        {
            pthread_cond_wait(&_cod, &_mtx);
        }
        void Wakeup()
        {
            pthread_cond_signal(&_cod);
        }
        //线程不可执行类内成员方法,因为这个方法具有隐含this指针,
        //可以访问静态方法,static方法没有this
        static void *Rountine(void *args)
        {
            pthread_detach(pthread_self());
            Pthreadpool<T> *tp = (Pthreadpool<T> *)args;

            while (1)
            {
                tp->Lock();
                while (tp->Isempty())
                {
                    tp->Wait();
                }
                T t;
                tp->PopTask(&t);
                tp->Unlock();
                t();
            }
        }
        void InitPool()
        {
            pthread_t tid;
            for (int i = 0; i < _cap; i++)
            {
                pthread_create(&tid, nullptr, Rountine, (void *)this);
            }
        }
        void PopTask(T *out)
        {
            *out = _taskque.front();
            _taskque.pop();
        }
        void PushTask(const T &in)
        {
            Lock();
            _taskque.push(in);
            Unlock();
            Wakeup();
        }
        ~Pthreadpool()
        {
            pthread_mutex_destroy(&_mtx);
            pthread_cond_destroy(&_cod);
        }
    };
    template <class T>
    Pthreadpool<T> *Pthreadpool<T>::ins = nullptr;
}

main.cc

#include"pthreadpool.hpp"
#include"task.hpp"
using namespace qzh1;
using namespace qzh;
int main()
{
    srand((long long)time(nullptr));
    
    cout<<"当前正在运行其他代码"<<endl;
    cout<<"当前正在运行其他代码"<<endl;
    cout<<"当前正在运行其他代码"<<endl;
    cout<<"当前正在运行其他代码"<<endl;
    cout<<"当前正在运行其他代码"<<endl;
    sleep(3);
    while(1)
    {
        usleep(100);
        int x=rand()%20+1;
        int y=rand()%20+1;
        string ops="+-*/%";
        Task t(x,y,ops[rand()%5]);
        Pthreadpool<Task>::GetInstance()->PushTask(t);
    }
    return 0;
}

task.hpp

#include<iostream>
using namespace std;
namespace qzh1
{
    class Task
    {
        private:
        int _x;
        int _y;
        char _op;
        public:
        Task(int x,int y,char op):_x(x),_y(y),_op(op)
        {}
        Task()
        {}
        ~Task()
        {}
        int Run()
        {
            int res=0;
            switch(_op)
            {
                case '+':
                res=_x+_y;
                break;
                case '-':
                res=_x-_y;
                break;
                case '*':
                res=_x*_y;
                break;
                case '/':
                res=_x/_y;
                break;
                case '%':
                res=_x%_y;
                break;
                default:
                cout<<"bug"<<endl;
            }
            cout<<"当前任务正在被thread["<<pthread_self()<<"]处理,结果为: "<<_x<<_op<<_y<<"="<<res<<endl;
        }
        int operator()()
        {
            return Run(); 
        }
    };
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值