简单实现线程池

1.线程池的基本概念

所谓的线程池就是事先创建好指定数目的线程,当同步队列为空的时候,线程全部处于等待状态,一旦同步队列被添加了事务,线程池就从同步队列中取事务并进行处理,处理完成之后又会重新获取同步队列中的事务。如果同步队列为空,就再次处于等待状态;如果没有空闲线程但是有新任务产生就放在同步队列中,等待线程执行完当前事务之后才能执行。

线程池的优点:

①降低资源的消耗:通过重复利用线程可以减少因频繁创建和销毁线程所带来的消耗。

②提高响应速度:当执行同步队列中的事务的时候,省去了创建线程的时间。

③提高线程的可管理性:线程是稀缺资源,如果无限制的创建线程,不仅会消耗系统的资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。

线程池的缺点:

①适应于生存周期较短的任务,不适应于又长又大的任务。

②不能对线程池中的任务设置优先级。

③不能标识线程的各个状态:比如启动线程、终止线程。

④对于任意给定的应用程序域,只能允许一个线程池与之对应。

⑤线程池中的所有线程都处于多线程单元中,如果想把线程放在单线程单元中,线程池就废掉了。

2.使用线程池的目的

由于创建线程存在一定的开销,无止尽的开新的线程会给系统产生大量的消耗,所以通过线程池使得线程能够重用从而处理无限的事务,避免每次使用线程都初始化。

3.线程池的工作原理

3.1主要组成:

(1)同步队列:以链表的形式创建一个同步队列,同步队列的主要工作就是通过Put()函数向队列里面添加事务,通过Get()函数从队列里面取出事务。

(2)线程池:主要由线程组(注:线程组里面存放的时thread类型的共享只能指针,指向工作的线程)构成,通过Start()函数向线程组中添加numThreads个线程,并使得每一个线程调用RunThread()函数来获取同步队列的事务并执行事务;通过Stop()函数停止线程池的工作。

3.2工作情况:

情况1:同步队列为空,主程序没有向同步队列中添加事务,线程池中的线程全部处于等待状态

情况2:同步队列满了,任务添加此时进入等待状态,等同步队列不满,继续执行添加工作

情况3:同步队列为空,主程序执行任务添加的数量小于线程的数量

情况4:同步队列不为空,但也没有满,线程池中所有的线程都在执行相应的事务,于此同时主程序向同步队列中添加事务。

3.3代码实现:

#include <iostream>
#include <mutex>
#include <list>
#inlcude <functional>
#include <condition_variable>
using namespace std;

//共享队列:
template <class T>
class SyncQueue
{
private:
      list<T> m_queue;
      mutex m_mutex;
      condition_variable m_IsFull;//客户端从共享队列中取事务的时候需要判断是否满了,满了就等待
      condition_variable m_IsEmpty;//服务端从共享队列总取事务的时候需要判断是为为空,空了就等待
      bool NeedStop;
      int maxSize;
public: 
      SyncQueue(int size):maxSize(size),NeedStop(false){}
      ~SynQueue()
      {
            Stop();
      }
      //往共享队列中添加事务
      void Put(T& task)
      {
            Add(task);
      }
       void Put(T&& task)
      {
            Add(std::forward<T>(task));
      }
      void Add(T&& task)
      {
             unique_lock<mutex>locker(m_mutex);
             IsFull.wait(locker,[]->bool{return NeedStop||NotFull();});
             if(NeedStop)
             {
                     return;
             }
             m_queue.push_back(std::forward<T>(tesk));
             IsEmpty.notify_one();
      }
      //从共享队列中取出事务
      void Get(list<T>& ls )//取出全部事务
      {
             unique_lock<mutex>locker(m_mutex);
             IsEmpty.wait(locker,[]->bool{return NeedStop||NotEmpty();});
             if(NeedStop)
             {
                     return;
             }
             ls=std::move(m_queue);
             IsEmpty.notify_one();
      }
       void Get(T& tmp )//取出一个事务
      {
             unique_lock<mutex>locker(m_mutex);
             IsEmpty.wait(locker,[]->bool{return NeedStop||NotEmpty();});
             if(NeedStop)
             {
                     return;
             }
             tmp=m_queue.front();
             queue.pop();
             IsEmpty.notify_one();
      }
      //停止当前共享队列的运行
      void Stop()
      {
              {
              unique_lock<mutex>locker(m_mutex);
              NeedStop=true;
              }
              IsEmpty.notify_all();
              IsFull.notify_all();
      }
      
      bool NotEmpty()
      {
               unique_lock<mutex>locker(m_mutex);
               return !m_queue.empty();
      }
      bool NotFull()
      {
               unique_lock<mutex>locker(m_mutex);
               return !m_queue.size()==maxSize;
      }
}

using Task=std::functional<void(void)>;
int MaxTaskCount=100;//规定线程组的最大容量
//线程池:
class ThreadPool()
{
private:
        SyncQueue<Task> m_queue;
        list<make_shared<std::thread>>m_thread_group;
        atomic_bool running;
        std::once_flag m_flag;
        void RunThread()
       {
               while(running)
               {
                       std::list<Task> list;
                       m_queue.Get(list);
                       for(auto t:list)
                       {
                               if(!running)
                               {
                                       return;
                               }
                               t();
                       }
               }
       }
        void StopThreadPool()
        {
                m_queue.Stop();
                running=false;
                for(auto& th:m_thread_group)
                {
                      if(th)
                      {
                             th->join();
                      }
                }
                m_thread_group.clear();
        }
public:
        ThreadPool():m_queue(MaxTaskCount)
        {}
        ~ThreadPool()
        {
              Stop();
        }
        //将事务添加到共享队列中
        void AddTask(Task&& t)
        {
                  m_queue.push_back(std::forward<Task>(t));
        }
         void AddTask(const Task& t)
        {
                  m_queue.push_back(t);
        }
        //开始线程池的工作
        void start(int NumThreads=thread::hardware_concurrency())
        {
                running=true;
                for(int i=0;i<NumThreads;++i)
                {
                         m_thread_group.push_back(make_shared<thread>(&ThreadPool::RunThread,this));
                }
        }
        //停止线程池的工作
        void Stop()
        {
              std::call_once(m_flas,[this]{StopThreadPool();});
        }
}

//测试代码:
void fun(thread::id thdid  )
{
	cout << thdid << endl;
}
void funa(ThreadPool& pool)
{
	cout << "void funa" << endl;
	for (int i = 0; i < 10; ++i)
	{
		thread::id thdid = this_thread::get_id();
		Task ft = std::bind(fun, thdid);
		pool.AddTask(ft);//将事务添加到队列中
	}
}
void TestThreadPool()
{
	ThreadPool pool;
	pool.Start(5);//首先线程池启动创建五个线程,然后每一个线程开始启动运行,向队列中取事务发现没有事务,因此挂起
	std::this_thread::sleep_for(std::chrono::seconds(2));
	std::thread tha(funa, std::ref(pool));//启动线程tha,调用funa函数,这个函数会给线程池里面的队列添加事务—>函数fun
	tha.join();
}
int main()
{
	TestThreadPool();
	return 0;
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

仟各

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值