•线程池就是有一堆已经创建好了的线程,当有新的任务需要处理的时候,就从这个池子里面取一个空闲等待的线程来处理该任务,当处理完成了就再次把该线程放回池中,以供后面的任务使用,当池子里的线程全都处理忙碌状态时,这时任务需要稍作等待。

•线程的创建和销毁比之进程的创建和销毁是轻量级的,但是当我们的任务需要大量进行大量线程的创建和销毁操作时,这个消耗就会变成的相当大。线程池的好处就在于线程复用,一个任务处理完成后,当前线程可以直接处理下一个任务,而不是销毁后再创建,非常适用于连续产生大量并发任务的场合。

线程池实例:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h> typedef struct task
{
void *(*process) (void *arg);
void *arg;
struct task *next;
} Cthread_task; /*线程池结构*/
typedef struct
{
pthread_mutex_t queue_lock; /* 互斥量 */
pthread_cond_t queue_ready; /* 条件变量 */ /*链表结构,线程池中所有等待任务*/
Cthread_task *queue_head; /*是否销毁线程池*/
int shutdown;
pthread_t *threadid; /*线程池中处理线程总数目*/
int max_thread_num; /*当前等待的任务数*/
int cur_task_size; } Cthread_pool; static Cthread_pool *pool = NULL; void *thread_routine (void *arg); void pool_init (int max_thread_num)
{
int i = 0; pool = (Cthread_pool *) malloc (sizeof (Cthread_pool));
/* 初始化互斥锁 */
pthread_mutex_init (&(pool->queue_lock), NULL);
/*初始化条件变量*/
pthread_cond_init (&(pool->queue_ready), NULL);
/* 初始化链表 */
pool->queue_head = NULL;
/* 最大线程数 */
pool->max_thread_num = max_thread_num;
/* 当前等待线程数 */
pool->cur_task_size = 0;
/* 线程池状态 */
pool->shutdown = 0; pool->threadid = (pthread_t *) malloc (max_thread_num * sizeof (pthread_t)); for (i = 0; i < max_thread_num; i++)
{
pthread_create (&(pool->threadid[i]), NULL, thread_routine, NULL); /* 创建三个线程 */
}
} /*向线程池中加入任务*/
int pool_add_task (void *(*process) (void *arg), void *arg)
{
/*构造一个新任务*/
Cthread_task *task = (Cthread_task *) malloc (sizeof (Cthread_task));
task->process = process;
task->arg = arg;
task->next = NULL; pthread_mutex_lock (&(pool->queue_lock));
/*将任务加入到等待队列中*/
Cthread_task *member = pool->queue_head; /* 找出线程池等待链表的头 */
if (member != NULL) /* 头部不为空,表明已经有线程在等待 */
{
while (member->next != NULL)
member = member->next;
member->next = task;
}
else /* 否则头部为空,直接将任务挂到等待链表头部 */
{
pool->queue_head = task;
} pool->cur_task_size++;
pthread_mutex_unlock (&(pool->queue_lock)); pthread_cond_signal (&(pool->queue_ready)); /* 唤醒线程池里睡眠的线程,尽管可能没有休眠的 */ return 0;
} /*销毁线程池,等待队列中的任务不会再被执行,但是正在运行的线程会一直
把任务运行完后再退出*/
int pool_destroy ()
{
if (pool->shutdown)
return -1;/*防止两次调用*/
pool->shutdown = 1; /*唤醒所有等待线程,线程池要销毁了*/
pthread_cond_broadcast (&(pool->queue_ready)); /*阻塞等待线程退出,否则就成僵尸了*/
int i;
for (i = 0; i < pool->max_thread_num; i++)
pthread_join (pool->threadid[i], NULL);
free (pool->threadid); /*销毁等待队列*/
Cthread_task *head = NULL;
while (pool->queue_head != NULL)
{
head = pool->queue_head;
pool->queue_head = pool->queue_head->next;
free (head);
}
/*条件变量和互斥量也别忘了销毁*/
pthread_mutex_destroy(&(pool->queue_lock));
pthread_cond_destroy(&(pool->queue_ready)); free (pool);
/*销毁后指针置空是个好习惯*/
pool=NULL;
return 0;
} void * thread_routine (void *arg)
{
printf ("starting thread 0x%x\n", pthread_self ());
while (1)
{
pthread_mutex_lock (&(pool->queue_lock)); while (pool->cur_task_size == 0 && !pool->shutdown)
{
printf ("thread 0x%x is waiting\n", pthread_self ());
pthread_cond_wait (&(pool->queue_ready), &(pool->queue_lock));
} /*线程池要销毁了*/
if (pool->shutdown)
{
/*遇到break,continue,return等跳转语句,千万不要忘记先解锁*/
pthread_mutex_unlock (&(pool->queue_lock));
printf ("thread 0x%x will exit\n", pthread_self ());
pthread_exit (NULL);
} printf ("thread 0x%x is starting to work\n", pthread_self ()); /*待处理任务减1,并取出链表中的头元素*/
pool->cur_task_size--;
Cthread_task *task = pool->queue_head; /* 从链表头取任务 */
pool->queue_head = task->next; /* 重置链表头 */
pthread_mutex_unlock (&(pool->queue_lock)); /*调用回调函数,执行任务*/
(*(task->process)) (task->arg);
free (task);
task = NULL;
}
/*这一句应该是不可达的*/
pthread_exit (NULL);
} void * myprocess (void *arg)
{
printf ("threadid is 0x%x, working on task %d\n", pthread_self (),*(int *) arg);
sleep (1);/*休息一秒,延长任务的执行时间*/
return NULL;
} int main (int argc, char **argv)
{
pool_init (3);/*线程池中最多三个活动线程*/ /*连续向池中投入10个任务*/
int *workingnum = (int *) malloc (sizeof (int) * 10);
int i;
for (i = 0; i < 10; i++)
{
workingnum[i] = i;
pool_add_task (myprocess, &workingnum[i]);
}
/*等待所有任务完成*/
sleep (5);
/*销毁线程池*/
pool_destroy (); free (workingnum); return 0;
}

unix中的线程池技术详解的更多相关文章

  1. Delphi中的线程类 - TThread详解

    Delphi中的线程类 - TThread详解 2011年06月27日 星期一 20:28 Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大多数Delphi书藉都有说到,但基本 ...

  2. 用 ThreadPoolExecutor/ThreadPoolTaskExecutor 线程池技术提高系统吞吐量(附带线程池参数详解和使用注意事项)

    1.概述 在Java中,我们一般通过集成Thread类和实现Runnnable接口,调用线程的start()方法实现线程的启动.但如果并发的数量很多,而且每个线程都是执行很短的时间便结束了,那样频繁的 ...

  3. JAVA线程池原理详解二

    Executor框架的两级调度模型 在HotSpot VM的模型中,JAVA线程被一对一映射为本地操作系统线程.JAVA线程启动时会创建一个本地操作系统线程,当JAVA线程终止时,对应的操作系统线程也 ...

  4. JAVA线程池原理详解一

    线程池的优点 1.线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用. 2.可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃. 线 ...

  5. JAVA线程池原理详解(1)

    线程池的优点 1.线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用. 2.可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃. 线 ...

  6. 基于Netty包中的Recycler实现的对象池技术详解

    一.业务背景 当项目中涉及到频繁的对象的创建和回收的时候,就会出现频繁GC的情况,这时就出现了池化的技术来实现对象的循环使用从而避免对象的频繁回收,Netty包下的Recycler就实现了这一功能.当 ...

  7. 线程池ThreadPool详解

    http://www.cnblogs.com/kissdodog/archive/2013/03/28/2986026.html 一.CLR线程池 管理线程开销最好的方式: 尽量少的创建线程并且能将线 ...

  8. JDK提供的四种线程池代码详解

    一.线程池什么时候使用,会给我们带来什么好处? 如果很多用户去访问服务器,用户访问服务器的时间是非常短暂的,那么有可能在创建线程和销毁线程上花费的时间会远远大于访问所消耗的时间,如果采用线程池会使线程 ...

  9. Executor线程池原理详解

    线程池 线程池的目的就是减少多线程创建的开销,减少资源的消耗,让系统更加的稳定.在web开发中,服务器会为了一个请求分配一个线程来处理,如果每次请求都创建一个线程,请求结束就销毁这个线程.那么在高并发 ...

随机推荐

  1. python3之range()

    python range() 函数可创建一个整数列表,一般用在 for 循环中. 函数语法(左闭右开) Python3 range() 函数返回的是一个可迭代对象(类型是对象),而不是列表类型, 所以 ...

  2. 使用Built-in formatting来创建log字符串

    在一次哦测试中,sonar-qube总是报Use the built-in formatting to contruct this argument, 在网上查了一下,原来它是推荐这样做: log.i ...

  3. datattable循环读取数据用于循环遍历checkboxlist里的项目

    DataTable dt = bptb.GetList("Pro_ID="+id).Tables[0]; foreach (ListItem li in from DataRow ...

  4. python基础四(json\os\sys\random\string模块、文件、函数)

    一.文件的修改 文件修改的两种思路: 1.把文件内容拿出来,做修改后,清空原来文件的内容,然后把修改过的文件内容重新写进去. 步骤: 1.打开文件:f=open('file','a+')  #必须用a ...

  5. 解Bug之路-串包Bug

    解Bug之路-串包Bug 笔者很热衷于解决Bug,同时比较擅长(网络/协议)部分,所以经常被唤去解决一些网络IO方面的Bug.现在就挑一个案例出来,写出分析思路,以飨读者,希望读者在以后的工作中能够少 ...

  6. Jack Straws(POJ 1127)

    原题如下: Jack Straws Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 5555   Accepted: 2536 ...

  7. 必应API接口nodejs版

    近期,在研究百度.必应.API等的url提交API时,发现有用Go语言做工具的大佬的分享 利用 API 自动向搜索引擎提交网址(Go语言版) - pyList. 其中提到bing API提交方法,并给 ...

  8. vue | vue实现列表同时展开与单独展开

    需求:每个li标签在点击的时候,都同时展开. 但是碰见几个问题: 1.如果点第一个li 所有li都会展开: 2.点击第一个li,第一个li展开,点击第二个li,第一个li闭合,第二个li展开 这两种情 ...

  9. 【Nginx】冰河又一本超硬核Nginx PDF教程免费开源!!

    写在前面 在 [冰河技术] 微信公众号中的[Nginx]专题,更新了不少文章,有些读者反馈说,在公众号中刷 历史文章不太方便,有时会忘记自己看到哪一篇了,当打开一篇文章时,似乎之前已经看过了, 但就是 ...

  10. powershell中使用Get-FileHash计算文件的hash值

    今天在公司一台windows服务器上.需要对两个文件进行比对,笔者首先就想到了可以使用md5校验 但是公司服务器上又不可以随意安装软件,于是笔者想到了可以试试windows自带的powershell中 ...