- 浏览: 407777 次
- 性别:
- 来自: 上海
文章分类
最新评论
-
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 1747strcpy() 字符串拷贝 char * ... -
cache写策略
2011-10-02 19:07 4744Write Through (完全写入) CPU向 ... -
实模式与保护模式
2011-10-02 16:30 11851. x86实模式介绍 x86体系的处理器刚开始时只有2 ... -
析构函数与virtual
2011-09-26 14:57 1347作为通常的原则,如 ... -
boost智能指针weak_ptr
2011-09-26 12:49 2788循环引用 引用计数是一种便利的内存管理机制,但它 ... -
boost智能指针shared_ptr
2011-09-26 12:37 2260最近项目中使用boost库的智能指针,感觉智能指针还是蛮 ... -
智能指针的原理和实现
2011-09-26 12:22 4440当类中有指针成员时,一般有两种方式来管理指针成员: ... -
死锁和饥饿的异同
2011-09-24 18:28 8110在多道程序系统中,同时有多个进程并发运行,共享系统资源,从而提 ... -
回调函数(callback)和仿函数(functor)
2011-09-23 15:09 2148回调函数(callback)与仿函数(functor)很多时候 ... -
memcpy, memccpy和memmove
2011-09-18 14:59 2404memcpy 声明:void *memcpy(void ... -
CPU页式内存管理
2011-09-17 20:25 3256页式内存管理 CPU的页式内存管理单元,负责把一个线性 ... -
CPU段式内存管理
2011-09-17 14:45 2979逻辑地址如何转换为线 ... -
逻辑地址与物理地址
2011-09-16 19:33 1503逻辑地址 (Logical Addres ... -
Union的一点使用心得
2011-09-07 21:57 1053Union的概念 “联合”是一种特殊的类,也是一种构造 ... -
虚函数、虚指针和虚表
2011-09-07 15:58 18657关于虚函数的背景知识 ... -
C++虚函数表解析
2011-09-07 14:58 1136C++中的虚函数的作用主要是实现了多态的机制。关于多态,简而言 ... -
函数指针和指针函数
2011-09-07 13:58 1023函数指针 在程序运行中,函数代码是程序的算法指令部分, ... -
大端和小端字节序
2011-09-06 21:53 1763关于字节序(大端法、小端法)的定义 《UNXI网络编程 ... -
memset, memcpy和strcpy的比较
2011-09-06 21:18 1958memset 用来对一段内存空间全部设置为某个字符,一般 ... -
C++中的static完全解析
2011-09-06 16:09 1091C++的static有两种用法:面向过程程序设计中的stati ...
相关推荐
接下来,我们将深入探讨如何在Linux环境下用C语言实现线程池。 首先,我们需要了解线程的基本概念。在C语言中,线程是进程内的一个执行单元,每个线程都有自己的程序计数器、栈和局部变量,但共享全局变量和其他...
下面是 Linux 系统下用 C 语言创建的一个线程池。线程池会维护一个任务链表(每个 CThread_worker 结构就是一个任务)。pool_init() 函数预先创建好 max_thread_num 个线程,每个线程执行 thread_routine() 函数。该...
6. **C++与Qt集成**:虽然标题是C语言实现,但描述中提到使用cpp文件后缀,这可能意味着代码可能混用了C++特性。如果在Qt环境中运行,可能利用了Qt的信号和槽机制来触发任务提交或线程池的状态变化。 7. **服务器...
在Linux下用C写的一个简易线程池。系统是RedHat 9,gcc版本"gcc version 4.1.2 20071124 (Red Hat 4.1.2-42)"。文件夹里的源码是按工程组织好的,在文件夹下的test目录下面有一个小的测试程序和Makefile,编译后即可...
本教程将深入探讨如何使用C语言在Linux上实现一个简单的线程池。 线程池的基本思想是预先创建一组线程,它们被存储在一个队列中,等待执行任务。当有新的任务到来时,线程池会分配一个空闲的线程来处理这个任务,而...
在提供的`CThread.cpp`和`CThread.h`文件中,我们可以推测这可能是实现线程池类的源代码。`CThread`类很可能包含了线程的实现,包括线程的启动、执行、同步和结束等操作。而`CThreadPool`类可能封装了上述的线程池...
### Linux线程池的C语言实现 #### 一、引言 在计算机编程领域,特别是Linux环境下,多线程技术被广泛应用于各种场景之中。传统上,开发者在需要的时候创建新线程来执行特定任务,任务完成后销毁线程。这种方式在...
总结来说,"C语言实现线程池"这个主题涉及到了Linux环境下的多线程编程,主要利用了pthread库。线程池通过预先创建并管理一组线程,减少了线程创建和销毁的开销,提高了系统资源利用率。理解和实现线程池不仅有助于...
linux系统下C语言 利用线程池技术实现CP命令 压缩包包含:源代码+开发说明PPT 线程池头文件: //任务 struct task { void *(*task)(void *arg); void *arg; struct task *next; }; //线程池 typedef struct ...
总的来说,这个Demo覆盖了Linux环境下C语言实现多线程编程的关键知识点,包括线程池的管理、线程同步(互斥锁)、状态机的设计、任务的调度以及高并发处理。通过对这些内容的学习和实践,开发者可以深入理解多线程...
在Linux操作系统中,C语言实现的线程池是一种优化多线程编程的高效技术。线程池通过预先创建一组线程并维护它们的状态,来处理并发任务,避免了频繁创建和销毁线程带来的开销。这个名为"libthreadpool"的库就是这样...
在本项目"简单线程池"中,我们将重点探讨如何用C语言在Linux环境下实现这样一个线程池系统,特别是关注其核心组件和设计原则。 首先,线程池的核心概念是线程复用,通过预先创建一组线程,可以避免频繁地创建和销毁...
在Linux环境下,使用C语言实现线程池具有一定的挑战性,但同时也提供了极高的灵活性和性能控制。C语言的底层操作能力和对内存的直接访问使得开发者能够更精细地控制线程的创建、调度和销毁过程。然而,这也意味着...
本文将深入探讨如何在Linux环境下利用C++实现一个功能完备的线程池,并提供一个可以直接使用的线程池类。 线程池的概念源于操作系统,它是一组预先创建并处于就绪状态的线程集合。当有新的任务需要执行时,线程池中...
在Linux环境下,通过C语言实现线程池是一种常见的编程实践。 在给定的资源中,"200行C代码实现简单线程池.doc"可能包含了详细的设计和实现步骤,以及如何在实际项目中应用线程池的文档。而"threadpool.c"则是实际的...
4. **Linux下实现线程池的工具和API** - **pthread库**:提供线程创建、同步等函数,如`pthread_create()`、`pthread_join()`、`pthread_mutex_t`和`pthread_cond_t`等。 - **标准C库**:如`queue.h`(链表)或...
在`C`语言中实现线程池,我们需要使用POSIX线程库(pthread),它提供了创建、同步和管理线程的接口。以下是一些关键步骤: 1. **线程池初始化**:在程序启动时,创建一定数量的线程放入线程池。这些线程通常处于...
在Linux环境下,C语言是一种...综上所述,"linux下c语言实现多线程web服务器"项目涵盖了操作系统、网络编程、线程管理、内存操作、并发控制等多个方面,对于理解系统级编程和Web服务的内部工作原理有着重要的实践价值。
在C语言实现线程池时,通常会使用POSIX线程库(pthread),它提供了创建、同步和管理线程的接口。例如,`pthread_create()`用于创建线程,`pthread_join()`用于等待线程结束,`pthread_mutex_*`和`pthread_cond_*`...
在Linux系统下,C语言是实现底层编程和高性能服务器应用的常见选择。本文将深入探讨如何利用C语言、Epoll事件模型、线程池以及数据库连接池来构建一个高并发的MySQL连接服务。 1. **C语言与MySQL连接**: C语言...