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

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

线程池实例:

#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. idea中右击的快捷键都找不到 Diagrams

    今天突然发现了一件很恐怖的事情,那就是我的IDEA的右击中找不到Diagrams了,因为我是用这个东西打开 .bpmn文件生成png的,突然没了.. 说一下解决吧 在FIle -> settin ...

  2. SpringBean容器启动流程+Bean的生命周期【附源码】

    如果对SpringIoc与Aop的源码感兴趣,可以访问参考:https://javadoop.com/,十分详细. 目录 Spring容器的启动全流程 Spring容器关闭流程 Bean 的生命周期 ...

  3. 仿VISIO连线

    说明: 1.未实现障碍物自动避让功能: 2.未实现添加图元到连线之间,连线自动避开新增图元功能: 后续再完善... version 1: package com.sunsheen.jfids.stud ...

  4. python中函数的参数:必传参数(位置参数)、默认值参数、参数组传参、关键字传参

    1.必传参数也叫做位置参数,因为必填,也必须对应位置 2.默认值参数如上图的word 3.参数组参数:传进去的是0个.或多个value的形式,,,和位置参数有点像,只传value值,但是没有限制个数 ...

  5. Robotframework自动化5-基础关键字介绍2

    一:时间 1.获取当前时间 Get time   2.获取当月时间    ${yyyy} ${mm} ${day} Get Time year,month,day${time} Catenate SE ...

  6. 刀哥多线程自动释放池autoreleasepool

    自动释放池 作用 自动释放对象的 所有 autorelease 的对象,在出了作用域之后,会被自动添加到最近创建的自动释放池中 自动释放池被销毁或者耗尽时,会向池中所有对象发送 release 消息, ...

  7. 自然常数e的含义

    e是一个重要的常数,但是它的直观含义却不像 π 那么明了.我们都知道,圆的周长与直径之比是一个常数,这个常数被称为圆周率,记作 π = 3.14159......可是e代表什么呢? e是“指数”(ex ...

  8. JDK的安装与环境变量的配置

    一.JDK的安装 1. JDK的下载地址     https://www.oracle.com/java/technologies/javase-downloads.html. 2.  当前最流行的是 ...

  9. (jvm调优)一、linux内存查看命令

    转载自https://blog.csdn.net/dongzhongyan/article/details/80067796 开始学习服务器性能查看以及调优 1.整体情况查看(任务管理器):top 第 ...

  10. 海量数据处理之布隆过滤器BloomFilter算法

    Bloom Filter是由Bloom在1970年提出的一种多哈希函数映射的快速查找算法.通常应用在一些需要快速判断某个元素是否属于集合,但是并不严格要求100%正确的场合.使用场景:数据量为100亿 ...