Linux__线程池及设计模式(单例模式)

线程池 :

线程池=线程安全队列+一大堆的线程(执行任务的线程)

线程池示例:

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

代码示例:

#pragma once 

#include <unistd.h>
#include <math.h>
#include <pthread.h>
#include <iostream>
#include <queue>

#define NUM 5

class Task
{
  public:
    int base;

  public:
    Task()
    {}

    Task(int _b)
      :base(_b)
    {}

    void Run()
    {
    std::cout << "thread is[" << pthread_self() << "] task run ... done: base# " << base << "pow is# " << pow(base, 2) << std::endl;
    }

    ~Task()
    {}
};

class ThreadPool 
{
  private:
    std::queue<Task*> q;
    int max_num;//线程总数
    pthread_mutex_t lock;
    pthread_cond_t cond;//让consumer等待
  
  public:
    void LockQueue()
    {
      pthread_mutex_lock(&lock);
    }

    void UnlockQueue()
    {
      pthread_mutex_unlock(&lock);
    }

    bool IsEmpty()
    {
      return q.size() == 0;
    }

    void ThreadWait()
    {
      pthread_cond_wait(&cond, &lock);
    }

    void ThreadWakeUp()
    {
      pthread_cond_signal(&cond);//指定唤醒
    }

    void ThreadsWakeUP()
    {
      pthread_cond_broadcast(&cond);//唤醒所有
    }

  public:
    ThreadPool(int _max=NUM)
      :max_num(_max)
    {}
    
    static void *Routine(void *arg)//内部成员函数带this指针,回调函数一个参数
    {
      ThreadPool *this_p = (ThreadPool*)arg;
      while(true)
      {
        this_p->LockQueue();
        while(this_p->IsEmpty())//没任务就一直等待
        {
         this_p->ThreadWait();
        }
        
        Task t;
        this_p->Get(t);//取任务
        this_p->UnlockQueue();
        t.Run();//执行任务在释放锁后
      }
    }

    void ThreadPoolInit()
    {
       pthread_mutex_init(&lock, nullptr);
       pthread_cond_init(&cond, nullptr);
        
       pthread_t t;
       for(int i = 0; i < max_num; ++i)
       {
         pthread_create(&t, nullptr, Routine, this);
       }
    }
    
    //外部server放任务
    void Put(Task &in)
    {
      LockQueue();
      q.push(&in);//塞任务
      UnlockQueue();

      ThreadWakeUp();
    }
    
    //内部ThreadPool执行任务
    void Get(Task &out)
    {
      Task *t = q.front();
      q.pop();
      out = *t;
    }

    ~ThreadPool()
    {
      pthread_mutex_destroy(&lock);
      pthread_cond_destroy(&cond);
    }
};

#include "ThreadPool.hpp"

int main()
{
  ThreadPool *tp = new ThreadPool();
  tp->ThreadPoolInit();
  
  //server一直构造任务
  while(true)
  {
    int x = rand()%10+1;
    Task t(x);
    tp->Put(t);
    sleep(1);
  }

  return 0;
}

在这里插入图片描述
线程池存在的价值

  1. 有任务,立马有线程进行服务,省掉了线程创建的时间。
  2. 有效防止server中线程过多,导致系统过载的问题。
  3. 可以避免在峰值压力下,系统资源耗尽的风险;并且可以统一对线程池中的线程进行管理,调度监控。

线程池vs进程池:

  1. 线程池占用资源更少,但鲁棒性不强。
  2. 进程池占用资源更多,但鲁棒性强。

单例模式

定义:确保一个类最多只有一个实例,并提供一个全局访问点

单例模式可以分为两种:预加载和延时加载

饿汉模式

预加载,再进一步解释就是还没有使用该单例对象,但是,该单例对象就已经被加载到内存了。

template<class T>
class singlen
{
public:
    //禁止构造,禁止拷贝构造,禁止拷贝
    static T* GetInstance()
    {
        return &data_;
    }
private:
    static T data;
};

优点:程序运行速度很快;缺点:程序初始化的时候就耗时比较长。

懒汉模式–延时加载

资源在使用的时候才进行实例化,单例列的对象在使用的时候才进行实例化。

class singten
{
public:
	static singten* GetInstance();
private:
    signlen();
    volatile static singten* p;
};
static singten* GetInstance()
{
    if(p==NULL)
    {
        pthread_mutex_lock(&locK_);
        if(p==NULL)
        {
            p=new singten();
        }
        pthread_mutex_unlock(&lock_);
    }
    return p;
}

  1. 互斥锁保证线程安全
  2. 双重if判空,降低锁竞争的概率
  3. volatile关键字防止过度优化
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值