- 浏览: 400521 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
handong1587:
代码有一处错.query函数最后一行return的应该是:re ...
RMQ -
yuandong0828:
简洁的特别透彻细致,多谢,
虚函数、虚指针和虚表 -
adam_zs:
谢谢分享!
括号匹配问题 -
hongloumengyanzxw:
good[b][/b]
dup和dup2函数 -
chriszeng87:
最后第二种情况右下角的那个点是不是可以看作相交点的?上面的那种 ...
判断两个链表是否相交
什么时候需要创建线程池呢?简单的说,如果一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这时也是线程池该出场的机会了。如果线程创建和销毁时间相比任务执行时间可以忽略不计,则没有必要使用线程池了。
下面是Linux系统下用C语言创建的一个线程池。线程池会维护一个任务链表(每个CThread_worker结构就是一个任务)。
pool_init()函数预先创建好max_thread_num个线程,每个线程执thread_routine ()函数。该函数中
while (pool->cur_queue_size == 0) { pthread_cond_wait (&(pool->queue_ready),&(pool->queue_lock)); }
表示如果任务链表中没有任务,则该线程出于阻塞等待状态。否则从队列中取出任务并执行。
pool_add_worker()函数向线程池的任务链表中加入一个任务,加入后通过调用pthread_cond_signal (&(pool->queue_ready))唤醒一个出于阻塞状态的线程(如果有的话)。
pool_destroy ()函数用于销毁线程池,线程池任务链表中的任务不会再被执行,但是正在运行的线程会一直把任务运行完后再退出。
以下为详细的实现代码:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/types.h> #include <pthread.h> #include <assert.h> /* *线程池里所有运行和等待的任务都是一个CThread_worker *由于所有任务都在链表里,所以是一个链表结构 */ typedef struct worker { /*回调函数,任务运行时会调用此函数,注意也可声明成其它形式*/ void *(*process) (void *arg); void *arg;/*回调函数的参数*/ struct worker *next; } CThread_worker; /*线程池结构*/ typedef struct { pthread_mutex_t queue_lock; pthread_cond_t queue_ready; /*链表结构,线程池中所有等待任务*/ CThread_worker *queue_head; /*是否销毁线程池*/ int shutdown; pthread_t *threadid; /*线程池中允许的活动线程数目*/ int max_thread_num; /*当前等待队列的任务数目*/ int cur_queue_size; } CThread_pool; int pool_add_worker (void *(*process) (void *arg), void *arg); void *thread_routine (void *arg); static CThread_pool *pool = NULL; void pool_init (int max_thread_num) { 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_queue_size = 0; pool->shutdown = 0; pool->threadid = (pthread_t *) malloc (max_thread_num * sizeof (pthread_t)); int i = 0; for (i = 0; i < max_thread_num; i++) { pthread_create (&(pool->threadid[i]), NULL, thread_routine, NULL); } } /*向线程池中加入任务*/ int pool_add_worker (void *(*process) (void *arg), void *arg) { /*构造一个新任务*/ CThread_worker *newworker = (CThread_worker *) malloc (sizeof (CThread_worker)); newworker->process = process; newworker->arg = arg; newworker->next = NULL;/*别忘置空*/ pthread_mutex_lock (&(pool->queue_lock)); /*将任务加入到等待队列中*/ CThread_worker *member = pool->queue_head; if (member != NULL) { while (member->next != NULL) member = member->next; member->next = newworker; } else { pool->queue_head = newworker; } assert (pool->queue_head != NULL); pool->cur_queue_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_worker *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)); /*如果等待队列为0并且不销毁线程池,则处于阻塞状态; 注意 pthread_cond_wait是一个原子操作,等待前会解锁,唤醒后会加锁*/ while (pool->cur_queue_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 ()); /*assert是调试的好帮手*/ assert (pool->cur_queue_size != 0); assert (pool->queue_head != NULL); /*等待队列长度减去1,并取出链表中的头元素*/ pool->cur_queue_size--; CThread_worker *worker = pool->queue_head; pool->queue_head = worker->next; pthread_mutex_unlock (&(pool->queue_lock)); /*调用回调函数,执行任务*/ (*(worker->process)) (worker->arg); free (worker); worker = 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_worker (myprocess, &workingnum[i]); } /*等待所有任务完成*/ sleep (5); /*销毁线程池*/ pool_destroy (); free (workingnum); return 0; }
将上述所有代码放入threadpool.c文件中,
在Linux输入编译命令
$ gcc -o threadpool threadpool.c -lpthread
原文地址:http://hi.baidu.com/lifepath/blog/item/0eb8ea5d6321c244fbf2c0d0.html
发表评论
-
strcpy, memcpy, memmove, memset的实现
2011-10-15 17:12 1688strcpy() 字符串拷贝 char * ... -
cache写策略
2011-10-02 19:07 4688Write Through (完全写入) CPU向 ... -
实模式与保护模式
2011-10-02 16:30 11461. x86实模式介绍 x86体系的处理器刚开始时只有2 ... -
析构函数与virtual
2011-09-26 14:57 1310作为通常的原则,如 ... -
boost智能指针weak_ptr
2011-09-26 12:49 2742循环引用 引用计数是一种便利的内存管理机制,但它 ... -
boost智能指针shared_ptr
2011-09-26 12:37 2214最近项目中使用boost库的智能指针,感觉智能指针还是蛮 ... -
智能指针的原理和实现
2011-09-26 12:22 4390当类中有指针成员时,一般有两种方式来管理指针成员: ... -
死锁和饥饿的异同
2011-09-24 18:28 8045在多道程序系统中,同时有多个进程并发运行,共享系统资源,从而提 ... -
回调函数(callback)和仿函数(functor)
2011-09-23 15:09 2099回调函数(callback)与仿函数(functor)很多时候 ... -
memcpy, memccpy和memmove
2011-09-18 14:59 2328memcpy 声明:void *memcpy(void ... -
CPU页式内存管理
2011-09-17 20:25 3212页式内存管理 CPU的页式内存管理单元,负责把一个线性 ... -
CPU段式内存管理
2011-09-17 14:45 2943逻辑地址如何转换为线 ... -
逻辑地址与物理地址
2011-09-16 19:33 1451逻辑地址 (Logical Addres ... -
Union的一点使用心得
2011-09-07 21:57 1007Union的概念 “联合”是一种特殊的类,也是一种构造 ... -
虚函数、虚指针和虚表
2011-09-07 15:58 18572关于虚函数的背景知识 ... -
C++虚函数表解析
2011-09-07 14:58 1089C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言 ... -
函数指针和指针函数
2011-09-07 13:58 991函数指针 在程序运行中,函数代码是程序的算法指令部分, ... -
大端和小端字节序
2011-09-06 21:53 1720关于字节序(大端法、小端法)的定义 《UNXI网络编程 ... -
memset, memcpy和strcpy的比较
2011-09-06 21:18 1921memset 用来对一段内存空间全部设置为某个字符,一般 ... -
C++中的static完全解析
2011-09-06 16:09 1024C++的static有两种用法:面向过程程序设计中的stati ...
相关推荐
linux下C语言实现线程池
linux线程池创建c实现 linux线程池创建c实现 linux线程池创建c实现 linux线程池创建c实现 linux线程池创建c实现 linux线程池创建c实现
linux线程池,c语言实现,只是文件后缀名用的是cpp方便在qt里面测试,两种版本,都是参考网上的资料做了一些处理之后的
在Linux下用C写的一个简易线程池。系统是RedHat 9,gcc版本"gcc version 4.1.2 20071124 (Red Hat 4.1.2-42)"。文件夹里的源码是按工程组织好的,在文件夹下的test目录下面有一个小的测试程序和Makefile,编译后即可...
一个linux下的c实现的线程池,其中包括线程池的创建、销毁、线程状态等操作。
linux系统下C语言 利用线程池技术实现CP命令 压缩包包含:源代码+开发说明PPT 线程池头文件: //任务 struct task { void *(*task)(void *arg); void *arg; struct task *next; }; //线程池 typedef struct ...
linux 下用线程pthread写线程池,从而实现多生产者和消费者
由C语言实现简单的线程池,任务调配,合理创建销毁线程处理任务
通常我们使用多线程的方式是,需要时创建一个新的线程,在这个新的线程里执行特定的任务,然后在任务完成后退出。这在一般的应用里已经能够满足我们应用的需要,毕竟我们并不是什么时候都需要创建大量的线程,并在...
C语言线程池实现实例
在Linux 系统下面用C 语言实现的高并发服务器的代码,具体用到了Epoll,线程池,数据库连接池
使用C语言实现一个基本线程池,包含Linux下条件变量的使用、线程池创建与销毁等等
linux下通过200行C代码实现简单线程池,附源代码和文档说明: 200行C代码实现简单线程池.doc threadpool.c
Linux下线程池的C语言实现,可以稍微参考一下。
在Linux 系统下面用C 语言实现的高并发服务器的代码,具体用到了Epoll,线程池,数据库连接池。 具体可以看下连接http://blog.csdn.net/wuyuxing24/article/details/48758927
操作系统课程项目,在linux下用c语言实现了多线程web服务器。可以选择不同的调度算法,来执行web请求,有FCFS, SJF。采用线程池设计思想实现。
linux pthreadpool实现和线程池的用处 简单易懂 互斥和信号量使用
简单的linux多线程实现,含互斥锁的使用
用来备份《Linux下分别使用C和C++语言实现线程池》里的线程池图;已备修改,仅供自己使用,请不要下载。文章链接https://blog.csdn.net/AnChenliang_1002/article/details/124643323
这是一个用c写的一个线程池函数,分多个文档,还有sourceInsight的工程文件,大家可以方便的打开来看。