Chinaunix首页 | 论坛 | 博客
  • 博客访问: 892042
  • 博文数量: 299
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 2493
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-21 10:07
个人简介

Linux后台服务器编程。

文章分类

全部博文(299)

文章存档

2015年(2)

2014年(297)

分类: C/C++

2014-10-24 21:44:58

之前都是参考别人的代码,现如今自己动手来写一个个人版本的线程池,线程池的实现本身并不复杂,无非就是创建一些线程然后让这些线程处于条件等待状态(可以用条件变量,也可以用信号量来实现)。这是最基本的原理,原理的理解很简单,但重要的是实现的细节问题。


线程池的实现:
包含内容:
1、线程数量N;
2、线程的工作内容函数,void* worker(void* arg);
3、共享数据,这里使用标准库中的list来实现,在实现过程中为了通用性,使用C++模板,
template
list m_queue;
4、互斥锁、信号量;


包含的各个内容中需要注意:
1、数量调整随着性能的增长的变化;
2、工作函数,在pthread_create()中,封装成类的线程池中在创建线程的时候要把worker设置成为static类型,否则会涉及类型转换问题,无法创建线程。
3、因为工作函数worker要使用共享数据,但是在类中static函数不可访问对象的内容,所以要把共享数据的内容设置成为static,这里也要注意一下类中的静态数据的初始化问题。
4、保持多线程的互斥和同步,同样设置成为static类型。

main.cc:

点击(此处)折叠或打开

  1. #include <iostream>
  2. #include <stdlib.h>

  3. #include <unistd.h>

  4. #include "locker.h"
  5. #include "threadpool.h"

  6. using namespace std;

  7. int main(){
  8.     threadpool<int> pool;

  9.     int arr[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};//注意传递给线程池的地址需要是请求的数据的地址,不能是临时对象的地址。
  10.     for(int i = 0; i < 10; i++){
  11.         pool.append(arr+i);
  12.     }

  13.     sleep(10);

  14.     return 0;
  15. }
locker.h

点击(此处)折叠或打开

  1. #ifndef LOCKER_H
  2. #define LOCKER_H

  3. #include <iostream>
  4. #include <pthread.h>
  5. #include <semaphore.h>
  6. using namespace std;

  7. class locker{
  8. public:
  9.     locker(){
  10.         if(pthread_mutex_init(&m_locker, NULL) != 0){
  11.             cout << "pthread_mutex_init failed." << endl;
  12.             exit(1);
  13.         }
  14.     }

  15.     ~locker(){
  16.         pthread_mutex_destroy(&m_locker);
  17.     }

  18.     bool lock(){
  19.         return pthread_mutex_lock(&m_locker) == 0;
  20.     }

  21.     bool unlock(){
  22.         return pthread_mutex_unlock(&m_locker) == 0;
  23.     }

  24. private:
  25.     pthread_mutex_t m_locker;
  26. };


  27. class sem{
  28. public:
  29.     sem(){
  30.         if(sem_init(&m_sem, 0, 0) != 0){
  31.             cout << "sem_init failed." << endl;
  32.             exit(1);
  33.         }
  34.     }

  35.     ~sem(){
  36.         sem_destroy(&m_sem);
  37.     }

  38.     bool wait(){
  39.         return sem_wait(&m_sem) == 0;
  40.     }

  41.     bool post(){
  42.         return sem_post(&m_sem) == 0;
  43.     }

  44. private:
  45.     sem_t m_sem;
  46. };

  47. class cond{
  48. public:
  49.     cond(){
  50.         if(pthread_mutex_init(&m_mutex, NULL) != 0){
  51.             cout << "pthread_mutex_init() of cond failed " << endl;
  52.             exit(1);
  53.         }
  54.         if(pthread_cond_init(&m_cond, NULL) != 0){
  55.             pthread_mutex_destroy(&m_mutex);
  56.             cout << "pthread_cond_init() of cond failed " << endl;
  57.             exit(1);
  58.         }
  59.     }

  60.     ~cond(){
  61.         pthread_mutex_destroy(&m_mutex);
  62.         pthread_cond_destroy(&m_cond);
  63.     }

  64.     bool wait(){
  65.         int ret = 0;
  66.         pthread_mutex_lock(&m_mutex);
  67.         ret = pthread_cond_wait(&m_cond, &m_mutex);
  68.         pthread_mutex_unlock(&m_mutex);
  69.         return ret == 0;
  70.     }

  71.     bool signal(){
  72.         return pthread_cond_signal(&m_cond) == 0;
  73.     }

  74. private:
  75.     pthread_mutex_t m_mutex;
  76.     pthread_cond_t m_cond;
  77. };

  78. #endif
threadpool:

点击(此处)折叠或打开

  1. #ifndef THREADPOLL_H
  2. #define THREADPOLL_H

  3. #include <iostream>
  4. #include <pthread.h>
  5. #include <list>
  6. #include <unistd.h>

  7. #include "locker.h"

  8. using namespace std;

  9. #define N 8

  10. using namespace std;


  11. template <typename T>
  12. class threadpool{
  13. public:
  14.     threadpool();
  15.     ~threadpool();
  16.     bool append(T* request);

  17. private:
  18.     static void* worker(void* arg);

  19. private:
  20.     static pthread_t* m_threads;
  21.     static locker m_locker;
  22.     static sem m_sem;
  23.     static list<T*> m_queue;
  24.     static bool m_stop;
  25. };

  26. template <typename T>
  27. pthread_t* threadpool<T>::m_threads = NULL;

  28. template <typename T>
  29. bool threadpool<T>::m_stop = false;

  30. template <typename T>
  31. locker threadpool<T>::m_locker;

  32. template <typename T>
  33. sem threadpool<T>::m_sem;

  34. template <typename T>
  35. list<T*> threadpool<T>::m_queue;

  36. template <typename T>
  37. threadpool<T>::threadpool(){
  38.     m_threads = new pthread_t[N];
  39.     if(m_threads == NULL){
  40.         cout << "new pthread_t[N] error." << endl;
  41.         exit(1);
  42.     }
  43.     for(int i = 0; i < N; i++){
  44.         if(pthread_create(m_threads+i, NULL, worker, NULL) != 0){
  45.             delete [] m_threads;
  46.             cout << "m_threads[] pthread_create failed." << endl;
  47.             exit(1);
  48.         }else{
  49.             cout << "m_threads[" << i << "] create successfully." << endl;
  50.         }
  51.         if(pthread_detach(m_threads[i])){
  52.             delete [] m_threads;
  53.             cout << "m_threads[] pthread_create failed." << endl;
  54.             exit(1);
  55.         }
  56.     }
  57. }


  58. template <typename T>
  59. threadpool<T>::~threadpool(){
  60.     delete[] m_threads;
  61.     m_stop = true;
  62. }


  63. template <typename T>
  64. bool threadpool<T>::append(T* request){
  65.     m_locker.lock();

  66.     m_queue.push_back(request);

  67.     m_locker.unlock();
  68.     
  69.     m_sem.post();

  70.     return true;
  71. }


  72. template <typename T>
  73. void* threadpool<T>::worker(void* arg){
  74. //    threadpool* pool = (threadpool*)arg;
  75.     T* temp;
  76.     while(m_stop == false){
  77.         m_sem.wait();
  78.         m_locker.lock();
  79.     
  80.         temp = m_queue.front();
  81.         m_queue.pop_front();
  82.     
  83.         m_locker.unlock();
  84.     
  85.         cout << "operations in workers of threadpool." << *temp << endl;; //对request的操作

  86.         sleep(1);
  87.     }
  88. }


  89. #endif


以上只是简单的代码小例,不可作为正式工程使用,未考虑到的地方很多如防御性编程等。



阅读(1488) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~