本文转载自:http://blog.csdn.net/yusiguyuan/article/details/18401277

一、线程池

大多数的网络服务器,包括Web服务器都具有一个特点,就是单位时间内必须处理数目巨大的连接请求,但是处理时间却是比较短的。在传统的多线程服务器模型中是这样实现的:一旦有个请求到达,就创建一个新的线程,由该线程执行任务,任务执行完毕之后,线程就退出。这就是"即时创建,即时销毁"的策略。尽管与创建进程相比,创建线程的时间已经大大的缩短,但是如果提交给线程的任务是执行时间较短,而且执行次数非常频繁,那么服务器就将处于一个不停的创建线程和销毁线程的状态。这笔开销是不可忽略的,尤其是线程执行的时间非常非常短的情况。

  线程池就是为了解决上述问题的,它的实现原理是这样的:在应用程序启动之后,就马上创建一定数量的线程,放入空闲的队列中。这些线程都是处于阻塞状态,这些线程只占一点内存,不占用CPU。当任务到来后,线程池将选择一个空闲的线程,将任务传入此线程中运行。当所有的线程都处在处理任务的时候,线程池将自动创建一定的数量的新线程,用于处理更多的任务。执行任务完成之后线程并不退出,而是继续在线程池中等待下一次任务。当大部分线程处于阻塞状态时,线程池将自动销毁一部分的线程,回收系统资源。

  下面是一个简单线程池的实现,这个线程池的代码是我参考网上的一个例子实现的,由于找不到出处了,就没办法注明参考自哪里了。它的方案是这样的:程序启动之前,初始化线程池,启动线程池中的线程,由于还没有任务到来,线程池中的所有线程都处在阻塞状态,当一有任务到达就从线程池中取出一个空闲线程处理,如果所有的线程都处于工作状态,就添加到队列,进行排队。如果队列中的任务个数大于队列的所能容纳的最大数量,那就不能添加任务到队列中,只能等待队列不满才能添加任务到队列中。

  主要由两个文件组成一个threadpool.h头文件和一个threadpool.c源文件组成。源码中已有重要的注释,就不加以分析了。

  threadpool.h文件:

  1. struct job
  2. {
  3. void* (*callback_function)(void *arg);    //线程回调函数
  4. void *arg;                                //回调函数参数
  5. struct job *next;
  6. };
  7. struct threadpool
  8. {
  9. int thread_num;                   //线程池中开启线程的个数
  10. int queue_max_num;                //队列中最大job的个数
  11. struct job *head;                 //指向job的头指针
  12. struct job *tail;                 //指向job的尾指针
  13. pthread_t *pthreads;              //线程池中所有线程的pthread_t
  14. pthread_mutex_t mutex;            //互斥信号量
  15. pthread_cond_t queue_empty;       //队列为空的条件变量
  16. pthread_cond_t queue_not_empty;   //队列不为空的条件变量
  17. pthread_cond_t queue_not_full;    //队列不为满的条件变量
  18. int queue_cur_num;                //队列当前的job个数
  19. int queue_close;                  //队列是否已经关闭
  20. int pool_close;                   //线程池是否已经关闭
  21. };
  22. //================================================================================================
  23. //函数名:                   threadpool_init
  24. //函数描述:                 初始化线程池
  25. //输入:                    [in] thread_num     线程池开启的线程个数
  26. //                         [in] queue_max_num  队列的最大job个数
  27. //输出:                    无
  28. //返回:                    成功:线程池地址 失败:NULL
  29. //================================================================================================
  30. struct threadpool* threadpool_init(int thread_num, int queue_max_num);
  31. //================================================================================================
  32. //函数名:                    threadpool_add_job
  33. //函数描述:                  向线程池中添加任务
  34. //输入:                     [in] pool                  线程池地址
  35. //                          [in] callback_function     回调函数
  36. //                          [in] arg                     回调函数参数
  37. //输出:                     无
  38. //返回:                     成功:0 失败:-1
  39. //================================================================================================
  40. int threadpool_add_job(struct threadpool *pool, void* (*callback_function)(void *arg), void *arg);
  41. //================================================================================================
  42. //函数名:                    threadpool_destroy
  43. //函数描述:                   销毁线程池
  44. //输入:                      [in] pool                  线程池地址
  45. //输出:                      无
  46. //返回:                      成功:0 失败:-1
  47. //================================================================================================
  48. int threadpool_destroy(struct threadpool *pool);
  49. //================================================================================================
  50. //函数名:                    threadpool_function
  51. //函数描述:                  线程池中线程函数
  52. //输入:                     [in] arg                  线程池地址
  53. //输出:                     无
  54. //返回:                     无
  55. //================================================================================================
  56. void* threadpool_function(void* arg);

 threadpool.c文件:

  1. #include "threadpool.h"
  2. struct threadpool* threadpool_init(int thread_num, int queue_max_num)
  3. {
  4. struct threadpool *pool = NULL;
  5. do
  6. {
  7. pool = malloc(sizeof(struct threadpool));
  8. if (NULL == pool)
  9. {
  10. printf("failed to malloc threadpool!\n");
  11. break;
  12. }
  13. pool->thread_num = thread_num;
  14. pool->queue_max_num = queue_max_num;
  15. pool->queue_cur_num = 0;
  16. pool->head = NULL;
  17. pool->tail = NULL;
  18. if (pthread_mutex_init(&(pool->mutex), NULL))
  19. {
  20. printf("failed to init mutex!\n");
  21. break;
  22. }
  23. if (pthread_cond_init(&(pool->queue_empty), NULL))
  24. {
  25. printf("failed to init queue_empty!\n");
  26. break;
  27. }
  28. if (pthread_cond_init(&(pool->queue_not_empty), NULL))
  29. {
  30. printf("failed to init queue_not_empty!\n");
  31. break;
  32. }
  33. if (pthread_cond_init(&(pool->queue_not_full), NULL))
  34. {
  35. printf("failed to init queue_not_full!\n");
  36. break;
  37. }
  38. pool->pthreads = malloc(sizeof(pthread_t) * thread_num);
  39. if (NULL == pool->pthreads)
  40. {
  41. printf("failed to malloc pthreads!\n");
  42. break;
  43. }
  44. pool->queue_close = 0;
  45. pool->pool_close = 0;
  46. int i;
  47. for (i = 0; i < pool->thread_num; ++i)
  48. {
  49. pthread_create(&(pool->pthreads[i]), NULL, threadpool_function, (void *)pool);
  50. }
  51. return pool;
  52. } while (0);
  53. return NULL;
  54. }
  55. int threadpool_add_job(struct threadpool* pool, void* (*callback_function)(void *arg), void *arg)
  56. {
  57. assert(pool != NULL);
  58. assert(callback_function != NULL);
  59. assert(arg != NULL);
  60. pthread_mutex_lock(&(pool->mutex));
  61. while ((pool->queue_cur_num == pool->queue_max_num) && !(pool->queue_close || pool->pool_close))
  62. {
  63. pthread_cond_wait(&(pool->queue_not_full), &(pool->mutex));   //队列满的时候就等待
  64. }
  65. if (pool->queue_close || pool->pool_close)    //队列关闭或者线程池关闭就退出
  66. {
  67. pthread_mutex_unlock(&(pool->mutex));
  68. return -1;
  69. }
  70. struct job *pjob =(struct job*) malloc(sizeof(struct job));
  71. if (NULL == pjob)
  72. {
  73. pthread_mutex_unlock(&(pool->mutex));
  74. return -1;
  75. }
  76. pjob->callback_function = callback_function;
  77. pjob->arg = arg;
  78. pjob->next = NULL;
  79. if (pool->head == NULL)
  80. {
  81. pool->head = pool->tail = pjob;
  82. pthread_cond_broadcast(&(pool->queue_not_empty));  //队列空的时候,有任务来时就通知线程池中的线程:队列非空
  83. }
  84. else
  85. {
  86. pool->tail->next = pjob;
  87. pool->tail = pjob;
  88. }
  89. pool->queue_cur_num++;
  90. pthread_mutex_unlock(&(pool->mutex));
  91. return 0;
  92. }
  93. void* threadpool_function(void* arg)
  94. {
  95. struct threadpool *pool = (struct threadpool*)arg;
  96. struct job *pjob = NULL;
  97. while (1)  //死循环
  98. {
  99. pthread_mutex_lock(&(pool->mutex));
  100. while ((pool->queue_cur_num == 0) && !pool->pool_close)   //队列为空时,就等待队列非空
  101. {
  102. pthread_cond_wait(&(pool->queue_not_empty), &(pool->mutex));
  103. }
  104. if (pool->pool_close)   //线程池关闭,线程就退出
  105. {
  106. pthread_mutex_unlock(&(pool->mutex));
  107. pthread_exit(NULL);
  108. }
  109. pool->queue_cur_num--;
  110. pjob = pool->head;
  111. if (pool->queue_cur_num == 0)
  112. {
  113. pool->head = pool->tail = NULL;
  114. }
  115. else
  116. {
  117. pool->head = pjob->next;
  118. }
  119. if (pool->queue_cur_num == 0)
  120. {
  121. pthread_cond_signal(&(pool->queue_empty));        //队列为空,就可以通知threadpool_destroy函数,销毁线程函数
  122. }
  123. if (pool->queue_cur_num == pool->queue_max_num - 1)
  124. {
  125. pthread_cond_broadcast(&(pool->queue_not_full));  //队列非满,就可以通知threadpool_add_job函数,添加新任务
  126. }
  127. pthread_mutex_unlock(&(pool->mutex));
  128. (*(pjob->callback_function))(pjob->arg);   //线程真正要做的工作,回调函数的调用
  129. free(pjob);
  130. pjob = NULL;
  131. }
  132. }
  133. int threadpool_destroy(struct threadpool *pool)
  134. {
  135. assert(pool != NULL);
  136. pthread_mutex_lock(&(pool->mutex));
  137. if (pool->queue_close || pool->pool_close)   //线程池已经退出了,就直接返回
  138. {
  139. pthread_mutex_unlock(&(pool->mutex));
  140. return -1;
  141. }
  142. pool->queue_close = 1;        //置队列关闭标志
  143. while (pool->queue_cur_num != 0)
  144. {
  145. pthread_cond_wait(&(pool->queue_empty), &(pool->mutex));  //等待队列为空
  146. }
  147. pool->pool_close = 1;      //置线程池关闭标志
  148. pthread_mutex_unlock(&(pool->mutex));
  149. pthread_cond_broadcast(&(pool->queue_not_empty));  //唤醒线程池中正在阻塞的线程
  150. pthread_cond_broadcast(&(pool->queue_not_full));   //唤醒添加任务的threadpool_add_job函数
  151. int i;
  152. for (i = 0; i < pool->thread_num; ++i)
  153. {
  154. pthread_join(pool->pthreads[i], NULL);    //等待线程池的所有线程执行完毕
  155. }
  156. pthread_mutex_destroy(&(pool->mutex));          //清理资源
  157. pthread_cond_destroy(&(pool->queue_empty));
  158. pthread_cond_destroy(&(pool->queue_not_empty));
  159. pthread_cond_destroy(&(pool->queue_not_full));
  160. free(pool->pthreads);
  161. struct job *p;
  162. while (pool->head != NULL)
  163. {
  164. p = pool->head;
  165. pool->head = p->next;
  166. free(p);
  167. }
  168. free(pool);
  169. return 0;
  170. }

测试文件main.c文件:

  1. #include "threadpool.h"
  2. void* work(void* arg)
  3. {
  4. char *p = (char*) arg;
  5. printf("threadpool callback fuction : %s.\n", p);
  6. sleep(1);
  7. }
  8. int main(void)
  9. {
  10. struct threadpool *pool = threadpool_init(10, 20);
  11. threadpool_add_job(pool, work, "1");
  12. threadpool_add_job(pool, work, "2");
  13. threadpool_add_job(pool, work, "3");
  14. threadpool_add_job(pool, work, "4");
  15. threadpool_add_job(pool, work, "5");
  16. threadpool_add_job(pool, work, "6");
  17. threadpool_add_job(pool, work, "7");
  18. threadpool_add_job(pool, work, "8");
  19. threadpool_add_job(pool, work, "9");
  20. threadpool_add_job(pool, work, "10");
  21. threadpool_add_job(pool, work, "11");
  22. threadpool_add_job(pool, work, "12");
  23. threadpool_add_job(pool, work, "13");
  24. threadpool_add_job(pool, work, "14");
  25. threadpool_add_job(pool, work, "15");
  26. threadpool_add_job(pool, work, "16");
  27. threadpool_add_job(pool, work, "17");
  28. threadpool_add_job(pool, work, "18");
  29. threadpool_add_job(pool, work, "19");
  30. threadpool_add_job(pool, work, "20");
  31. threadpool_add_job(pool, work, "21");
  32. threadpool_add_job(pool, work, "22");
  33. threadpool_add_job(pool, work, "23");
  34. threadpool_add_job(pool, work, "24");
  35. threadpool_add_job(pool, work, "25");
  36. threadpool_add_job(pool, work, "26");
  37. threadpool_add_job(pool, work, "27");
  38. threadpool_add_job(pool, work, "28");
  39. threadpool_add_job(pool, work, "29");
  40. threadpool_add_job(pool, work, "30");
  41. threadpool_add_job(pool, work, "31");
  42. threadpool_add_job(pool, work, "32");
  43. threadpool_add_job(pool, work, "33");
  44. threadpool_add_job(pool, work, "34");
  45. threadpool_add_job(pool, work, "35");
  46. threadpool_add_job(pool, work, "36");
  47. threadpool_add_job(pool, work, "37");
  48. threadpool_add_job(pool, work, "38");
  49. threadpool_add_job(pool, work, "39");
  50. threadpool_add_job(pool, work, "40");
  51. sleep(5);
  52. threadpool_destroy(pool);
  53. return 0;
  54. }

二、线程池补充

上面的文章介绍了线程池的原理及意义。

下面,介绍的这个线程池与上面提到的那个线程池有一部分相似的地方。

  主要区别为:

    1、线程池中的每个线程都有自己的互斥量和条件变量,而不是线程池共享一个。

    2、线程池中的线程在程序结束时,等待线程池中线程停止的机制不同。

  该程序主要由两个文件构成,分别为ThreadPool.h和ThreadPool.cpp文件。

  ThreadPool.h文件:

  1. #define MAXT_IN_POOL 200
  2. #define BUSY_THRESHOlD 0.5
  3. #define MANAGE_INTREVAL 2
  4. class ThreadPool;
  5. typedef void (*dispatch_fn)(void*);
  6. //线程函数参数
  7. typedef struct tagThread
  8. {
  9. pthread_t thread_id;           //线程ID
  10. pthread_mutex_t thread_mutex;  //信号量
  11. pthread_cond_t thread_cond;    //条件变量
  12. dispatch_fn do_job;            //调用的函数,任务
  13. void* args;                    //函数参数
  14. ThreadPool *parent;            //线程池指针
  15. }_thread;
  16. //线程池
  17. class ThreadPool
  18. {
  19. public:
  20. //================================================================================================
  21. //函数名:                  ThreadPool
  22. //函数描述:                构造函数
  23. //输入:                    [in] max_threads_in_pool 线程池最大线程数
  24. //输入:                    [in] min_threads_in_pool 线程池最小问题数
  25. //输出:                    无
  26. //返回:                    无
  27. //================================================================================================
  28. ThreadPool(unsigned int max_threads_in_pool, unsigned int min_threads_in_pool = 2);
  29. ~ThreadPool();
  30. //================================================================================================
  31. //函数名:                  dispatch_threadpool
  32. //函数描述:                将任务加入线程池,由线程池进行分发
  33. //输入:                    [in] dispatch_me 调用的函数地址
  34. //输入:                    [in] dispatch_me 函数参数
  35. //输出:                    无
  36. //返回:                    无
  37. //================================================================================================
  38. void dispatch_threadpool(dispatch_fn dispatch_me, void* dispatch_me);
  39. private:
  40. pthread_mutex_t tp_mutex;  //信号量
  41. pthread_cond_t tp_idle;    //线程池中线程有空闲线程的条件变量
  42. pthread_cond_t tp_full;    //线程池中线程为满的条件变量
  43. pthread_cond_t tp_empty;   //线程池中线程为空的条件变量
  44. int tp_min;                //线程池的最小线程数
  45. int tp_max;                //线程池的最大线程数
  46. int tp_avail;              //线程池中空闲的线程数
  47. int tp_total;              //线程池中已创建的线程数
  48. _thread** tp_list;         //指向线程池中所有空闲线程的参数的指针
  49. bool tp_stop;              //线程池是否已停止
  50. //================================================================================================
  51. //函数名:                  add_avail
  52. //函数描述:                加入空闲线程
  53. //输入:                    [in] avail 线程的参数
  54. //输出:                    无
  55. //返回:                    成功:true,失败:false
  56. //================================================================================================
  57. bool add_avail(_thread* avail);
  58. //================================================================================================
  59. //函数名:                  work_thread
  60. //函数描述:                线程函数
  61. //输入:                    [in] args 参数
  62. //输出:                    无
  63. //返回:                    无
  64. //================================================================================================
  65. static void* work_thread(void* args);
  66. //================================================================================================
  67. //函数名:                  add_thread
  68. //函数描述:                添加一个线程
  69. //输入:                    [in] dispatch_me 函数指针
  70. //输入:                    [in] args        函数参数
  71. //输出:                    无
  72. //返回:                    无
  73. //================================================================================================
  74. bool add_thread(dispatch_fn dispatch_me, void* args);
  75. //================================================================================================
  76. //函数名:                  syn_all
  77. //函数描述:                等待线程池中所有线程空闲
  78. //输入:                    无
  79. //输出:                    无
  80. //返回:                    无
  81. //================================================================================================
  82. void syn_all();
  83. };

ThreadPool.cpp文件:

    1. ThreadPool::ThreadPool(unsigned int max_threads_in_pool, unsigned int min_threads_in_pool)
    2. {
    3. pthread_t manage_id;
    4. if (min_threads_in_pool <= 0 || max_threads_in_pool < 0 || min_threads_in_pool > max_threads_in_pool || max_threads_in_pool > MAXT_IN_POOL)
    5. {
    6. return ;
    7. }
    8. tp_avail = 0;      //初始化线程池
    9. tp_total = 0;
    10. tp_min = min_threads_in_pool;
    11. tp_max = max_threads_in_pool;
    12. tp_stop = false;
    13. tp_list = (_thread * *)    malloc(sizeof(void *) * max_threads_in_pool);
    14. if (NULL == tp_list)
    15. {
    16. return;
    17. }
    18. memset(tp_list, 0, sizeof(void *) * max_threads_in_pool);
    19. pthread_mutex_init(&tp_mutex, NULL);
    20. pthread_cond_init(&tp_idle, NULL);
    21. pthread_cond_init(&tp_full, NULL);
    22. pthread_cond_init(&tp_empty, NULL);
    23. }
    24. bool ThreadPool::add_avail(_thread* avail)
    25. {
    26. bool ret = false;
    27. pthread_mutex_lock(&tp_mutex);
    28. if (tp_avail < tp_max)
    29. {
    30. tp_list[tp_avail] = avail;
    31. tp_avail++;
    32. pthread_cond_signal(&tp_idle);  //线程池中有线程为空闲
    33. if (tp_avail >= tp_total)
    34. {
    35. pthread_cond_signal(&tp_full); //线程池中所有线程都为为空闲
    36. }
    37. ret = true;
    38. }
    39. pthread_mutex_unlock(&tp_mutex);
    40. return ret;
    41. }
    42. void* ThreadPool::work_thread(void* args)
    43. {
    44. _thread* thread = (_thread*) args;
    45. ThreadPool *pool = thread->parent;
    46. while (pool->tp_stop == false)
    47. {
    48. thread->do_job(thread->args);
    49. pthread_mutex_lock(&thread->thread_mutex); //执行完任务之后,添加到空闲线程队列中
    50. if (pool->add_avail(thread))
    51. {
    52. pthread_cond_wait(&thread->thread_cond, &thread->thread_mutex);
    53. pthread_mutex_unlock(&thread->thread_mutex);
    54. }
    55. else
    56. {
    57. pthread_mutex_unlock(&thread->thread_mutex);
    58. pthread_mutex_destroy(&thread->thread_mutex);
    59. pthread_cond_destroy(&thread->thread_cond);
    60. free(thread);
    61. break;
    62. }
    63. }
    64. pthread_mutex_lock(&pool->tp_mutex);
    65. pool->tp_total--;
    66. if (pool->tp_total <= 0)
    67. {
    68. pthread_cond_signal(&pool->tp_empty);
    69. }
    70. pthread_mutex_unlock(&pool->tp_mutex);
    71. return NULL;
    72. }
    73. bool ThreadPool::add_thread(dispatch_fn dispatch_me, void* args)  //添加一个线程
    74. {
    75. _thread* thread = NULL;
    76. pthread_attr_t attr;
    77. thread = (_thread *) malloc(sizeof(_thread));
    78. if (NULL == thread)
    79. {
    80. return false;
    81. }
    82. pthread_mutex_init(&thread->thread_mutex, NULL);
    83. pthread_cond_init(&thread->thread_cond, NULL);
    84. thread->do_job = dispatch_me;
    85. thread->args = args;
    86. thread->parent = this;
    87. pthread_attr_init(&attr);
    88. pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    89. if (pthread_create(&thread->thread_id, &attr, work_thread, (void *) thread) != 0)
    90. {
    91. pthread_mutex_destroy(&thread->thread_mutex);
    92. pthread_cond_destroy(&thread->thread_cond);
    93. pthread_attr_destroy(&attr);
    94. free(thread);
    95. return false;
    96. }
    97. tp_total++;
    98. return true;
    99. }
    100. void ThreadPool::dispatch_threadpool(dispatch_fn dispatch_me, void* args)
    101. {
    102. _thread* thread = NULL;
    103. pthread_mutex_lock(&tp_mutex);
    104. if (tp_avail <= 0 && tp_total >= tp_max) //无可用线程,而且线程数已达最大值,等待空闲线程
    105. {
    106. pthread_cond_wait(&tp_idle, &tp_mutex);
    107. }
    108. if (tp_avail <= 0)  //无可用线程,而且线程数未达最大值,添加线程
    109. {
    110. if (!add_thread(dispatch_me, args))
    111. {
    112. return;
    113. }
    114. }
    115. else   //有可用线程
    116. {
    117. tp_avail--;
    118. thread = tp_list[tp_avail];
    119. tp_list[tp_avail] = NULL;
    120. thread->do_job = dispatch_me;
    121. thread->args = args;
    122. pthread_mutex_lock(&thread->thread_mutex);
    123. pthread_cond_signal(&thread->thread_cond);
    124. pthread_mutex_unlock(&thread->thread_mutex);
    125. }
    126. pthread_mutex_unlock(&tp_mutex);
    127. }
    128. void ThreadPool::syn_all()
    129. {
    130. if (tp_avail < tp_total)   //等待线程池中所有线程都为空闲状态
    131. {
    132. pthread_cond_wait(&tp_full, &tp_mutex);
    133. }
    134. tp_stop = true;
    135. int i = 0;
    136. for (i = 0; i < tp_avail; i++)  //唤醒线程池中所有线程
    137. {
    138. _thread *thread = tp_list[i];
    139. pthread_mutex_lock(&thread->thread_mutex);
    140. pthread_cond_signal(&thread->thread_cond);
    141. pthread_mutex_unlock(&thread->thread_mutex);
    142. }
    143. if (tp_total > 0)
    144. {
    145. pthread_cond_wait(&tp_empty, &tp_mutex);  //等待线程池中所有线程都结束
    146. }
    147. }
    148. ThreadPool::~ThreadPool()
    149. {
    150. sleep(MANAGE_INTREVAL);
    151. pthread_mutex_lock(&tp_mutex);
    152. syn_all();                        //等待线程池为空
    153. int i = 0;
    154. for (i = 0; i < tp_total; i++)  //资源释放
    155. {
    156. free(tp_list[i]);
    157. tp_list[i] = NULL;
    158. }
    159. pthread_mutex_unlock(&tp_mutex);
    160. pthread_mutex_destroy(&tp_mutex);
    161. pthread_cond_destroy(&tp_idle);
    162. pthread_cond_destroy(&tp_full);
    163. pthread_cond_destroy(&tp_empty);
    164. free(tp_list);
    165. }

linux中线程池【转】的更多相关文章

  1. Java中java.util.concurrent包下的4中线程池代码示例

    先来看下ThreadPool的类结构 其中红色框住的是常用的接口和类(图片来自:https://blog.csdn.net/panweiwei1994/article/details/78617117 ...

  2. Java中线程池,你真的会用吗?

    在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及基本原理. 在文中有这样一段描述: 可以通过Executors静态工厂构建线程池,但一般不建 ...

  3. Java并发编程中线程池源码分析及使用

    当Java处理高并发的时候,线程数量特别的多的时候,而且每个线程都是执行很短的时间就结束了,频繁创建线程和销毁线程需要占用很多系统的资源和时间,会降低系统的工作效率. 参考http://www.cnb ...

  4. 沉淀再出发:java中线程池解析

    沉淀再出发:java中线程池解析 一.前言 在多线程执行的环境之中,如果线程执行的时间短但是启动的线程又非常多,线程运转的时间基本上浪费在了创建和销毁上面,因此有没有一种方式能够让一个线程执行完自己的 ...

  5. Java中线程池,你真的会用吗?ExecutorService ThreadPoolExcutor

    原文:https://www.hollischuang.com/archives/2888 在<深入源码分析Java线程池的实现原理>这篇文章中,我们介绍过了Java中线程池的常见用法以及 ...

  6. linux C 线程池(物不可穷也~)

    Linux 多线程编程之 线程池 的原理和一个简单的C实现,提高对多线程编 程的认知,同步处理等操作,以及如何在实际项目中高效的利用多线程开 发. 1.  线程池介绍 为什么需要线程池??? 目前的大 ...

  7. 基于linux与线程池实现文件管理

    项目要求 1.基本 用线程池实现一个大文件夹的拷贝,大文件夹嵌套很多小文件:实现复制到指定文件夹的全部文件夹. 2.扩充功能 显示进度条:拷贝耗时统计:类似linux的tree,不能直接用system ...

  8. Linux C++线程池

    .为什么需要线程池? 部分应用程序需要执行很多细小的任务,对于每个任务都创建一个线程来完成,任务完成后销毁线程,而这就会产生一个问题:当执行的任务所需要的时间T1小于等于创建线程时间T2和销毁线程时间 ...

  9. Linux下线程池的理解与简单实现

    首先,线程池是什么?顾名思义,就是把一堆开辟好的线程放在一个池子里统一管理,就是一个线程池. 其次,为什么要用线程池,难道来一个请求给它申请一个线程,请求处理完了释放线程不行么?也行,但是如果创建线程 ...

随机推荐

  1. Ubuntu 16.04配置国内高速apt-get更新源

    https://www.linuxidc.com/Linux/2017-11/148627.htm Ubuntu 16.04下载软件速度有点慢,因为默认的是从国外下载软件,那就更换到国内比较好的快速更 ...

  2. 用Monitor简单3步监控中间件ActiveMQ

    Apache ActiveMQ是一个基于JMX规范的纯Java消息中间件,它为应用系统提供高效.灵活的消息同步与异步传输处理.存储转发.可靠传输的特性. 消息队列对于应用的健康运行非常重要,作为运维人 ...

  3. linux环境下python的部署

    linux系统环境自带python2.6,但有时我们项目使用的版本可能是3.x以上等等,此时我们需要在linux中再安装项目所需的python版本,此时就涉及多版本共存问题了,很多同学在安装多个版本P ...

  4. Charles maplocal 时中文显示乱码问题

    用Charles对request进行Map Local后,app上看返回的中文是乱码? 是Map Local的文件编码有问题?是Charles设置有问题?是电脑环境有问题?哈哈,都不是 你是Andro ...

  5. java 泛型没有协变类型, 所以要重用extends, 但使用List<? extends Fruit> 可以是ArrayList<Fruit>()、ArrayList<Apple>()、ArrayList<Orange>(), 因此不能add元素进去

    class Fruit{} class Apple extends Fruit{} class SubApple extends Apple{} class Orange extends Fruit{ ...

  6. Java学习之路-RMI学习

    Java远程方法调用,即Java RMI(Java Remote Method Invocation)是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口.它使客户机上运行的程序可以调用远 ...

  7. elasticsearch 6.0在Ubuntu下的安装

    1:直接下载 elasticsearch 6.0  zip文件  https://www.elastic.co/downloads/past-releases 2:解压:进入到解压后的bin目录,执行 ...

  8. 用Python实现的数据结构与算法:开篇

    一.概述 用Python实现的数据结构与算法 涵盖了常用的数据结构与算法(全部由Python语言实现),是 Problem Solving with Algorithms and Data Struc ...

  9. hadoop streaming怎么设置key

    充分利用hadoop的map输出自动排序功能,能够有效提高计算效率.Hadoop streaming框架默认情况下会以'/t’作为分隔符,将每行第一个'/t’之前的部分作为key,其余内容作为valu ...

  10. Locust性能测试5-参数化批量注册

    前言 实现场景:所有并发虚拟用户共享同一份测试数据,并且保证虚拟用户使用的数据不重复. 例如,模拟10用户并发注册账号,总共有100个手机号,要求注册账号不重复,注册完毕后结束测试 准备数据 虚拟用户 ...