linux下c语言实现简单----线程池

linux下c语言实现简单----线程池

这两天刚好看完linux&c这本书的进程线程部分,学长建议可以用c语言实现一个简单的线程池,也是对线程知识的一个回顾与应用。线程的优点有好多,它是”轻量级的进程”,所需资源少,多线程共享数据空间,线程之间切换速度更快,可以减少服务器的闲置时间等。


那么我们要在往高层次讲它也有一些缺点,比如一个多线程的程序在创建和销毁线程的时候是比较费资源的,举一个例子,我们要是自己是一个普通饭店老板,当顾客来了我们再做饭,那么势必比较慢,这当然会使得顾客感受不好;但是我们要是KFC工作人员,来一个顾客,马上就能为他服务,这是因为我们提前准备好了汉堡。而线程池也正是这个原理,我们提前创建线程,让它们处在等待状态,要是有任务,就激活线程,执行完毕要是没有任务就继续等待。下面是IBM上对线程池背景介绍


线程池的技术背景 
在面向对象编程中,创建和销毁对象是很费时间的,因为创建一个对象要获取内存资源或者其它更多资源。在Java中更是如此,虚拟机将试图跟踪每一个对象,以便能够在对象销毁后进行垃圾回收。所以提高服务程序效率的一个手段就是尽可能减少创建和销毁对象的次数,特别是一些很耗资源的对象创建和销毁。如何利用已有对象来服务就是一个需要解决的关键问题,其实这就是一些”池化资源”技术产生的原因。比如大家所熟悉的数据库连接池正是遵循这一思想而产生的。
下面是我实现的代码:我的先城池大小为5,代码中我为它添加了10个任务。


#include<stdio.h>
#include<pthread.h>
#include<stdlib.h>
#include<errno.h>
#include<unistd.h>


typedef void*(*FUNC)(void* arg);                //指向函数的指针,用来指向我的线程函数。
typedef struct _thpool_jobqueue                 //任务队列
{
    FUNC                     routine;           //定义指向线程函数的指针routine
    void*                    arg;               //传向线程函数的参数
    struct _thpool_jobqueue  *next;
}thpool_jobqueue;
typedef struct _thpool_t                        //线程池
{
    int               max_thr_num;              //线程池的尺寸
    int               flag;                     //是否销毁的标志
    pthread_t         *thr_id;                  //线程ID指针
    pthread_cond_t    jobqueue_cond;            //条件变量
    pthread_mutex_t   jobqueue_mutex;           //互斥锁
    thpool_jobqueue   *jobqueue_head;           //指向任务队列的指针
}thpool_t;
static thpool_t * thpool = NULL;                //全局变量,指向线程池的指针


/*建议:为了结构更清晰,请从main函数开始,然后线程创建函数--->任务添加函数--->线程函数*/




void *thread_routine()                          //线程函数
{
    thpool_jobqueue *work;                        
    while(1)
    {
        pthread_mutex_lock(&thpool->jobqueue_mutex);              
        while((thpool->jobqueue_head == NULL) &&( thpool->flag == 0)) //如果此时没有任务,并且不打算销毁线程池
        {
            pthread_cond_wait(&thpool->jobqueue_cond,&thpool->jobqueue_mutex);//       就让抢到锁的在此等待,其他线程在锁的外边阻塞
        }
        if(thpool->flag != 0)                                         //每次可以执行的时候都判断下线程池是否要销毁
        {
            pthread_mutex_unlock(&thpool->jobqueue_mutex);
            pthread_exit(0);
        }
        work = thpool->jobqueue_head;                                 //若不销毁,则将任务添加到任务队列
        thpool->jobqueue_head = thpool->jobqueue_head->next;          //让任务指针指向下一个
        pthread_mutex_unlock(&thpool->jobqueue_mutex);
        work->routine(work->arg);                                     //work->routine = routine = func1
        free(work);
    }
}


void thpool_add_task(void*(*routine)(void *),void* arg)        //任务添加函数
{
    thpool_jobqueue  *work,*member;


    work = (thpool_jobqueue*)malloc(sizeof(thpool_jobqueue));  //准备任务,将添加到任务队列
    work->routine = routine;
    work->arg = arg;
    work->next = NULL;
    pthread_mutex_lock(&thpool->jobqueue_mutex);               //对任务队列操作必须保证只有一个线程
    member = thpool->jobqueue_head;
    if(!member)
    {
        thpool->jobqueue_head = work;                          //如果此任务是第一个任务
    }
    else
    {
        while(member->next != NULL)                            //如果不是第一个任务就添加到最后
            member = member->next;
        member->next = work;
    }
    pthread_cond_signal(&thpool->jobqueue_cond);
    pthread_mutex_unlock(&thpool->jobqueue_mutex);
}


void thpool_create(int max_thr_num)                   //线程创建函数
{
    int i;   
    thpool = (thpool_t *)malloc(sizeof(thpool_t));    
    if(!thpool)
    {
        perror("malloc thpool error");
    }
    thpool->flag = 0;                                 //初始化的过程
    thpool->max_thr_num = max_thr_num;                
    thpool->thr_id = (pthread_t*)malloc(max_thr_num*sizeof(pthread_t));
    thpool->jobqueue_head = NULL;
    pthread_mutex_init(&thpool->jobqueue_mutex,NULL);
    pthread_cond_init(&thpool->jobqueue_cond,NULL);
    for(i = 0;i < max_thr_num;i++)
    {
        pthread_create(&thpool->thr_id[i],NULL,thread_routine,NULL);  //创建线程的过程
    }
}
void thpool_destroy()                            //销毁线程池
{
    printf("线程池正在销毁\n");
    int i;
    thpool_jobqueue *member;  
    if(thpool->flag != 0)                        //先判断一下销毁标志是否已经销毁
    {
        return;
    }
    thpool->flag = 1;                            //将销毁标志至为1,即需要销毁
    pthread_mutex_lock(&thpool->jobqueue_mutex); 
    pthread_cond_broadcast(&thpool->jobqueue_cond);  //广播所有线程要销毁的通知
    pthread_mutex_unlock(&thpool->jobqueue_mutex);   
    for(i = 0;i < thpool->max_thr_num;i++)          
    {
        pthread_join(thpool->thr_id[i],NULL);     //等待所有线程都结束
    }
        free(thpool->thr_id);                      //将所有线程ID释放
    while(thpool->jobqueue_head)
    {
        member = thpool->jobqueue_head;
        thpool->jobqueue_head = thpool->jobqueue_head->next;
        free(member);                              //释放每一个任务
    }
    pthread_mutex_destroy(&thpool->jobqueue_mutex);//销毁锁
    pthread_cond_destroy(&thpool->jobqueue_cond);  //销毁条件变量
    free(thpool);                                  //销毁指向线程池的指针
    printf("销毁完成\n");


}


void *func1()
{
    printf("thread %u is running\n",pthread_self());
    sleep(3);                                     //让别的线程有机会抢锁
}


int main(int argc,char *argv[])
{
    int i;


    thpool_create(5);                             //在线程池里创建5个线程
    for(i = 0;i < 10;i++)
    {
        thpool_add_task(func1,NULL);
    }
    sleep(10);
    thpool_destroy();
}
下面是运行结果:
[kiosk@yangbodong 20150805]$ ./a.out 
thread 3508193024 is running
thread 3491407616 is running
thread 3499800320 is running
thread 3516585728 is running
thread 3483014912 is running
thread 3491407616 is running
thread 3508193024 is running
thread 3483014912 is running
thread 3516585728 is running
thread 3499800320 is running
线程池正在销毁
销毁完成


从运行结果中的进程号可以看出总共有5个线程在工作,任务分为两次被执行,前五个running是一次,后五个running是一次


线程池就是有一堆已经创建好了的线程,初始它们都处于空闲等待状态,当有新的任务需要处理的时候,就从这个池子里面取一个空闲等待的线程来处理该任务,当处理完成了就再次把该线程放回池中,以供后面的任务使用。当池子里的线程全都处理忙碌状态时,线程池中没有可用的空闲等待线程,此时,根据需要选择创建一个新的线程并置入池中,或者通知任务线程池忙,稍后再试。
       为什么要用线程池,线程的创建和销毁比之进程的创建和销毁是轻量级的,但是当一个应用需要频繁的创建和销毁线程,而任务执行的时间又非常短,这样线程创建和销毁的带来的开销就不容忽视,这是就可以使用线程池了(若线程创建和销毁时间相比任务执行时间可以忽略不计,则不必要使用线程池了)。线程池的好处就在于线程复用,一个任务处理完成后,当前线程可以直接处理下一个任务,而不是销毁后再创建,非常适用于连续产生大量并发任务的场合。
        线程池工作原理(线程池负责线程的创建,销毁和任务处理参数传递、唤醒和等待):
(1)创建若干线程,置入线程池 
(2)任务达到时,从线程池取空闲线程 
(3)取得了空闲线程,立即进行任务处理 
(4)否则新建一个线程,并置入线程池,执行(3) 
(5)如果创建失败或者线程池已满,根据设计策略选择返回错误或将任务置入处理队列,等待处理 
(6)销毁线程池




二、详解


1、简单的线程池代码一


(1)threadpool.h:


#ifndef _THREADPOOL_H_
#define _THREADPOOL_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
 
#define THWK_F_CLEAN    1    /* 设置此标志着threadpool正在进行清理操作,此时线程退出。 */
#define THWK_F_RUNNING    2    /* 设置这个标志主要是为了避免一个race condition,后述。 */
#define EINVAL 1
#define EBUSY 2
 
struct thread_worker_arg {
    void (*action)(void*);    /* user programmer指定的实际函数 */
    void *what;        /* action的参数 */
};
 
struct thread_worker {
    pthread_t id;            /* just as its name */
    struct thread_worker_arg arg;    /* 用于给sleepy_wrapper()传送参数,后述。 */
    pthread_mutex_t lock;        /* 用于实现线程池内空闲线程的休眠,它实际上并不保护什么临界区。 */
    struct thread_worker *next;    /* 用于链表线程池内的其他线程 */
    unsigned long long delay;    /* 未用,计划用于测量调度延迟。 */
    unsigned long flags;        /* 标志,后述。 */
};
 
struct thread_pool {
    pthread_mutex_t lock;        /* 用于同步对于thread_pool自身的访问操作 */
    struct thread_worker *first;    /* 所有线程链接于此 */
    int total;            /* 总线程数 */
    int current_nr;            /* 池内空闲线程数 */
};
struct thread_pool* thread_pool_create(int nr_to_create, pthread_attr_t *attr);
int thread_pool_lend(struct thread_pool *pool, void (*action)(void*), void* what, struct thread_worker **worker);
int thread_pool_giveback(struct thread_pool *pool, struct thread_worker *worker);
int thread_pool_clean(struct thread_pool *pool);
 
int thread_pool_is_running(struct thread_worker *worker);
void thread_pool_activate(struct thread_worker *worker);
#endif
(2)threadpool.c:
#include "threadpool.h"        /* #include了所有必要的系统头文件 */
 
/* 未用,计划用于测量调度延迟。 */
inline unsigned long long get_ticks(void)
{
    //    __asm__ ("rdtsc");
 
    return 0ULL;
}
 
/* 用于支持线程在被取消时的必要清理操作。 */
static void sleepy_wrapper_cleanup(void *voidp)
{
    struct thread_worker *worker = voidp;
 
    pthread_mutex_unlock(&worker->lock);
    free(worker);
}
 
/* 这就是线程池内线程的执行函数了。 */
static void* sleepy_wrapper(void *voidp)
{
    struct thread_worker *worker = voidp;
 
    while (1) {
        pthread_cleanup_push(sleepy_wrapper_cleanup, worker); /* 预设置上一个清理函数,防止线程取消时内存泄漏。 */
        pthread_mutex_lock(&worker->lock); /* 空闲线程应该休眠于此,这个mutex在创建thread pool时就锁住了。或者本循环结束时锁住。 */
        worker->delay = get_ticks() - worker->delay; /* 暂时无用。 */
        if (THWK_F_CLEAN & worker->flags) /* 线程池正在清理本身,所以线程至此就退出了。 */
            goto done; /* 你可能觉得这个goto用得有些多余,但如果不这样编译就会提示句法错误,因为pthread_cleanup_{push,pop}是用宏实现的!你可以参考一下它们的实现。 */
        worker->flags |= THWK_F_RUNNING; /* 后述。 */
        if (worker->arg.action) /* 进行线程实际的工作 */
            worker->arg.action(worker->arg.what);
done:
        pthread_mutex_unlock(&worker->lock); /* 解锁这个mutex,允许这个thread的下一次使用 */
        pthread_cleanup_pop(0);
        if (THWK_F_CLEAN & worker->flags) /* 清理线程池 */
            break;
        pthread_mutex_lock(&worker->lock); /* 先锁住这个锁,以让本循环开头的pthread_mutex_lock()使线程进入休眠。这个调用应该是成功的,否则就会引用deadlock。 */
        worker->flags &= ~THWK_F_RUNNING; /* 设计这个标志的意义在于防止有线程激活操作在以上unlock/lock之间发生,如果这样的话,就会引起deadlock,激活操作的实现后述。 */
    }
    pthread_exit(0);
}
 
/* 无需废话的函数。 */
pthread_t thread_pool_rawid(struct thread_worker *worker)
{
    return worker->id;
}
 
/* 如果线程被取消了,通知线程池忘记它,目前的实现很简单。*/
void thread_pool_forget(struct thread_pool *pool, struct thread_worker *worker)
{
    pool->total--;
}
 
/* 线程激活操作 */
void thread_pool_activate(struct thread_worker *worker)
{
    worker->delay = get_ticks();
    while (thread_pool_is_running(worker)) /* 防止出现deadlock */
        ;
    pthread_mutex_unlock(&worker->lock); /* 使sleepy_wrapper()内循环开头部分的lock()操作返回,即线程得以唤醒执行实际的action(what)。 */
}
 
/* 另一个无须废话的函数 */
int thread_pool_is_running(struct thread_worker *worker)
{
    return (worker->flags & THWK_F_RUNNING);
}
 
/* 从线程池中借出一个线程,其实就是一个从链表头中摘出thread_worker的简单函数 */
int thread_pool_lend(struct thread_pool *pool, void (*action)(void*), void* what, struct thread_worker **worker)
{
    if (!action || !pool || !worker)
        return -EINVAL;
 
    pthread_mutex_lock(&pool->lock);
    *worker = pool->first;
    if (worker) {
        (*worker)->arg.action = action;
        (*worker)->arg.what = what;
        pool->first = (*worker)->next;
        (*worker)->next = NULL;
        pool->current_nr--;
    }
    pthread_mutex_unlock(&pool->lock);
    return 0;
}
 
/* 向线程池里归还一个thread,头插法插入thread_worker链表。 */
int thread_pool_giveback(struct thread_pool *pool, struct thread_worker *worker)
{
    if (!pool || !worker)
        return -EINVAL;
 
    while (thread_pool_is_running(worker))
        ;
 
    pthread_mutex_lock(&pool->lock);
    worker->next = pool->first;
    pool->first = worker;
    worker->arg.action = NULL;
    worker->arg.what = NULL;
    pool->current_nr++;
    pthread_mutex_unlock(&pool->lock);
 
    return 0;
}
 
/* 虽然有点长,但仍然是无须废话:线程池创建 */
struct thread_pool* thread_pool_create(int nr_to_create, pthread_attr_t *attr)
{
    struct thread_pool *pool;
    struct thread_worker *worker;
    int i, chk;
 
    if (!nr_to_create)
        return NULL;
 
    pool = malloc(sizeof(struct thread_pool));
    if (!pool)
        return NULL;
 
    pool->first = NULL;
    pool->total = 0;
    pthread_mutex_init(&pool->lock, NULL);
 
    for (i=0; i<nr_to_create; ++i) {
        worker = malloc(sizeof(struct thread_worker));
        if (!worker)
            break;
        memset(worker, 0, sizeof(struct thread_worker));
 
        pthread_mutex_init(&worker->lock, NULL);
        pthread_mutex_lock(&worker->lock);
 
        chk = pthread_create(&worker->id, attr, sleepy_wrapper, (void*)worker);
        if (chk) {
            pthread_mutex_unlock(&worker->lock);
            pthread_mutex_destroy(&worker->lock);
            free(worker);
            break;
        }
        worker->next = pool->first;
        pool->first = worker;
    }
    
    pool->total = i;
    pool->current_nr = i;
    if (0 == i) {
        pthread_mutex_destroy(&pool->lock);
        free(pool);
        pool = NULL;
    }
    return pool;
}
 
/* 清理线程池。 */
int thread_pool_clean(struct thread_pool *pool)
{
    struct thread_worker *worker;
 
    pthread_mutex_lock(&pool->lock);
    if (pool->total != pool->current_nr) {
        pthread_mutex_unlock(&pool->lock);
        return -EBUSY;
    }
 
    while (NULL != (worker = pool->first)) {
        worker->flags = THWK_F_CLEAN; /* this is =, rather than |= ! */
        pthread_mutex_unlock(&worker->lock);
        pthread_join(worker->id, NULL);
        pool->first = worker->next;
        pthread_mutex_destroy(&worker->lock);
        free(worker);
    }
 
    pthread_mutex_unlock(&pool->lock);
    pthread_mutex_destroy(&pool->lock);
    free(pool);
    return 0;
}
(3)main.c:
#include "threadpool.h"
 
unsigned long long sum(unsigned long long start, unsigned long long end)
{
    unsigned long long sum;
 
    sum = 0;
    for (; start<=end; ++start)
        sum += start;
    return sum;
}
struct per_sum {
    unsigned long long sum, start, end;
    pthread_mutex_t lock;
    pthread_cond_t cond;
};
void threaded_sum(void *voidp)
{
    struct per_sum *per_sum = voidp;
    printf("thread %p start\n", voidp);
    if (!per_sum) {
        //printf("per_sum == NULL\n");
        return;
    }
    printf("+++++++++++++++start=%lld, end=%lld\n", per_sum->start, per_sum->end);
    per_sum->sum = sum(per_sum->start, per_sum->end);
    per_sum->start = per_sum->end = 0;
    pthread_mutex_lock(&per_sum->lock);
    printf("thread %p exit, end=%lld\n", voidp, per_sum->end);
    pthread_cond_signal(&per_sum->cond);
    pthread_mutex_unlock(&per_sum->lock);
}
 
int main(void)
{
    #define NR_THREADS    2
    struct thread_worker* workers[NR_THREADS];
    struct per_sum per_sums[NR_THREADS];
    struct thread_pool *pool;
    int i;
 
    unsigned long long start = 0, end = 0;
    unsigned long long result = 0;
    unsigned long long delta = 10;
 
    printf("thread_pool is running...\n");
 
    printf("+++++++++++++++init+++++++++++++++\n");
    printf("thread_pool create...\n");
    pool = thread_pool_create(NR_THREADS, NULL);
    if(!pool) exit(-1);
 
    for (i=0; i<NR_THREADS; ++i) {
        if (pthread_mutex_init(&per_sums[i].lock, NULL)) {
            printf("failed init mutex\n");
            exit(3);
        }
        if (pthread_cond_init(&per_sums[i].cond, NULL)) {
            printf("failed init cond\n");
            exit(4);
        }
        if (thread_pool_lend(pool, threaded_sum, (void*)&per_sums[i], &workers[i])) {
            printf("failed to lend thread %d\n", i);
            exit(5);
        }
    }
    start = 0;
    printf("++++++set value++++result=%lld++++\n", result);
    printf("thread_pool activate...\n");
    /* activate threads */
    for (i=0; i<NR_THREADS; i++) {
        per_sums[i].start = start;
        per_sums[i].end = per_sums[i].start + delta;
        start = per_sums[i].end + 1;
        thread_pool_activate(workers[i]);
    }
    printf("thread_pool wait...\n");
    for (i=0; i<NR_THREADS; i++) {
        pthread_mutex_lock(&per_sums[i].lock);
        while (per_sums[i].end != 0)
            pthread_cond_wait(&per_sums[i].cond, &per_sums[i].lock);
        result += per_sums[i].sum;
        pthread_mutex_unlock(&per_sums[i].lock);
    }
    /* activate threads again */
    printf("++++++set value again++++result=%lld++++\n", result);
    printf("thread_pool activate again...\n");
    for (i=0; i<NR_THREADS; i++) {
        per_sums[i].start = start;
        per_sums[i].end = per_sums[i].start + delta;
        start = per_sums[i].end + 1;
        thread_pool_activate(workers[i]);
    }
    end = per_sums[NR_THREADS-1].end;
    for (i=0; i<NR_THREADS; i++) {
        pthread_mutex_lock(&per_sums[i].lock);
        while (per_sums[i].end != 0)
            pthread_cond_wait(&per_sums[i].cond, &per_sums[i].lock);
        result += per_sums[i].sum;
        pthread_mutex_unlock(&per_sums[i].lock);
    }
    printf("thread_pool giveback...\n");
    for (i=0; i<NR_THREADS; ++i) {
        if (thread_pool_giveback(pool, workers[i])) {
            printf("failed to giveback thread %d\n", i);
            exit(6);
        }
        pthread_mutex_destroy(&per_sums[i].lock);
        pthread_cond_destroy(&per_sums[i].cond);
    }
    printf("thread_pool clean...\n");
    thread_pool_clean(pool);
    printf("*******sum = %lld******\n", result);
    return 0;
}
(4)编译运行:
gcc -o main main.c threadpool.c  -lpthread
./main


2、简单的线程池代码二


(1)threadpool.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <pthread.h>
#include <assert.h>
 
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));
        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) {
            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 (pool->cur_queue_size != 0);
        assert (pool->queue_head != NULL);
 
        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);
}
(2)main.c:
#include <stdio.h>
#include <stdlib.h>
 
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);
    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;
}
(3)编译运行:
gcc -o main main.c threadpool.c  -lpthread
./main

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值