一个简单的线程池

线程池

当我们需要多次使用线程时,需要多次创建并销毁线程。而创建并销毁线程的过程势必会消耗内存。线程池是一种多线程处理形式,提前创建多个线程,处理过程中将任务添加到任务队列,每个线程不断往复的从任务队列中获取任务、执行任务。避免了在处理短时间任务时创建与销毁线程的代价。

应用场景:

1.需要大量的线程来完成任务,且完成任务的时间比较短。 WEB服务器完成网页请求这样的任务,使用线程池技术是非常合适的。因为单个任务小,而任务数量巨大,你可以想象一个热门网站的点击次数。但对于长时间的任务,线程池的优点就不明显了。因为完成该任务时间可能比线程的创建时间大多了。

2.需要快速响应的需求。

3.突发性的大量需求,在没有线程池的情况下,将产生大量线程,而在短时间内产生大量线程可能会导致内存到达极限,出现错误。

在服务器使用一个线程来处理一个用户请求时,线程池可限制服务器中同时处理的用户数(等于线程池中线程总数)。

线程池示例:

1.创建固定数量线程的线程池,循环的从任务队列中获取任务对象;

2.获取到任务对象后,执行任务对象中的任务接口。

  1 #ifndef __THREADPOOL_H_
  2 #define __THREADPOOL_H_
  3 
  4 #include <iostream>
  5 #include <queue>
  6 #include <pthread.h>
  7 #include <unistd.h>
  8 using namespace std;
  9 
 10 typedef int (*hander) (int, int);
 11 
 12 class Task
 13 {
 14 public:
 15     int _x;
 16     int _y;
 17     hander _func;
 18 public:
 19     Task(const int& x, const int& y, hander func)
 20         :_x(x)
 21         ,_y(y)
 22         ,_func(func)
 23     {}
 24     void Run()
 25     {
 26         cout << pthread_self() << " result: " << _func(_x, _y) << endl;
 27     }
 28 };
 29 
 30 class ThreadPool
 31 {
 32 private:
 33     queue<Task> task_queue; //任务队列
 34     size_t thread_count;
 35     pthread_mutex_t mutex; //对任务队列的操作需保证线程安全
 36     pthread_cond_t cond; //任务队列为空时阻塞线程,加入新任务时唤醒线程。
 37 private:
 38     void LockQueue()
 39     {
 40         pthread_mutex_lock(&mutex);
 41     }
 42     void UnLockQueue()
 43     {
 44         pthread_mutex_unlock(&mutex);
 45     }
 46     void BlockThread()
 47     {
 48         pthread_cond_wait(&cond, &mutex);
 49     }
 50     void SignalThread()
 51     {
 52         pthread_cond_signal(&cond);
 53     }
 54     Task GetTask()
 55     {
 56         Task t = task_queue.front();
 57         task_queue.pop();
 58         return t;
 59     }
 60 
 61 public:
 62     ThreadPool(size_t count = 3)
 63         :thread_count(count)
 64     {}
 65     static void *run_func(void *arg) //static函数没有参数this
 66     {
 67         ThreadPool *tp = (ThreadPool *)arg; //不能用this指针,使用参数传入一个对象指针,用来访问成员方法
 68         while(1) //每个线程往复的拿任务,执行任务
 69         {
 70             tp->LockQueue();
 71             while(tp->task_queue.empty())
 72             {
 73                 tp->BlockThread(); //当前没有任务,线程被阻塞
 74             }
 75             //poptaskqueue
 76             Task t = tp->GetTask();
 77             //unlockmutex
 78             tp->UnLockQueue();
 79             //runtask
 80             t.Run(); //在锁外执行任务
 81         }
 82     }
 83     void InitThreadPool()
 84     {
 85         pthread_mutex_init(&mutex, NULL);
 86         pthread_cond_init(&cond, NULL);
 87         pthread_t tid;
 88         while(thread_count--)
 89         {
 90             pthread_create(&tid, NULL, run_func, (void *)this);
 91         }
 92     }
 93     void PutTask(const Task& t)
 94     {
 95         LockQueue();
 96         task_queue.push(t);
 97         UnLockQueue();
 98         SignalThread(); //当有新任务时,唤醒可能被阻塞的线程
 99     }
100     ~ThreadPool()
101     {
102         pthread_mutex_destroy(&mutex);
103         pthread_cond_destroy(&cond);
104     }
105 };
106 
107 class Singleton //单例
108 {
109 private:
110     static ThreadPool *tp;
111     pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
112 public:
113     ThreadPool *GetInstance()
114     {
115         if(tp == NULL)
116         {
117             pthread_mutex_lock(&mutex); //为null时再加锁,避免当已经存在对象时仍需要等待获得锁
118             if(tp == NULL) //再次判断可避免在第一次判断和获得锁之间,有其他线程先一步为单例获得对象,而导致非单例
119             {
120                 tp = new ThreadPool(5);
121                 tp->InitThreadPool();
122             }
123             pthread_mutex_unlock(&mutex);
124         }
125         return tp;
126     }
127 };
128 
129 ThreadPool *Singleton::tp = NULL;
130 
131 #endif
 1 #include "threadpool.hpp"
 2 #include <cstdlib>
 3 #include <ctime>
 4 
 5 int Add(int x, int y)
 6 {
 7     return x + y;
 8 }
 9 int Sub(int x, int y)
10 {
11     return x - y;
12 }
13 int Mul(int x, int y)
14 {
15     return x * y;
16 }
17 int Div(int x, int y)
18 {
19     return x / y;
20 }
21 
22 int main()
23 {
24     srand((unsigned int)time(NULL));
25     hander func_arr[] = {Add, Sub, Mul, Div}; //模拟线程执行的任务
26     ThreadPool *tp = Singleton().GetInstance();
27     while(1)
28     {
29         int x = rand() % 20 + 1;
30         int y = rand() % 5 + 1;
31         int index = rand() % 4;
32         Task t = Task(x, y, func_arr[index]);
33         cout << "Put task: " << x << " "<< index << " " << y << endl;
34         tp->PutTask(t);
35         sleep(1);
36     }
37     return 0;
38 }

 

posted @ 2019-07-01 15:03  大白的攻城狮  阅读(295)  评论(0编辑  收藏  举报