一个简单的线程池实现

一个简单的线程池实现

应用特点:

  • 用于执行大量的相对短暂的任务
  • 当任务增加的时候能够动态的增加线程池中线程的数量,直到达到一个阈值
  • 当任务执行完毕的时候,能够动态的销毁线程池中的线程
  • 线程池的实现本质上是生产者与消费者模型的应用. 生产者线程向任务队列中添加任务, 一旦队列中有任务到来, 如果有等待线程就唤醒来执行任务, 如果没有等待线程并且线程数没有达到阈值, 就创建新的线程来执行任务.
#ifndef _CONDITION_H_
#define _CONDITION_H_

#include <pthread.h>

typedef struct condition
{
    pthread_mutex_t pmutex;
    pthread_cond_t   pcond;
} condition_t;

int condition_init(condition_t *cond);
int condition_lock(condition_t *cond);
int condition_unlock(condition_t *cond);
int condition_wait(condition_t *cond);
int condition_timedwait(condition_t *cond, const struct timespec *abstime);
int condition_sinal(condition_t *cond);
int condition_broadcast(condition_t *cond);
int condition_destroy(condition_t *cond);

#endif /*_CONDITION_H_*/

/* =================================================== */
#include "condition.h"
int condition_init(condition_t *cond)
{
    int status;
    if (status = pthread_mutex_init(&cond->pmutex, NULL))
        return status;

    if (status = pthread_cond_init(&cond->pcond, NULL))
        return status;

    return 0;
}

int condition_lock(condition_t *cond)
{
    return pthread_mutex_lock(&cond->pmutex);
}

int condition_unlock(condition_t *cond)
{
    return pthread_mutex_unlock(&cond->pmutex);
}

int condition_wait(condition_t *cond)
{
    return pthread_cond_wait(&cond->pcond, &cond->pmutex);
}

int condition_timedwait(condition_t *cond, const struct timespec *abstime)
{
    return pthread_cond_timedwait(&cond->pcond, &cond->pmutex, abstime)
}

int condition_sinal(condition_t *cond)
{
    return pthread_cond_signal(&cond->pcond);
}

int condition_broadcast(condition_t *cond)
{
    return pthread_cond_broadcast(&cond->pcond);
}

int condition_destroy(condition_t *cond)
{
    int status;
    if (status = pthread_mutex_destroy(&cond->pmutex))
        return status;

    if (status = pthread_cond_destroy(&cond->pcond))
        return status;

    return 0;
}


// 任务结构体, 将任务放入队列由线程池中的线程来执行
typedef struct task
{
    void *(*run)(void *arg); //任务回调函数
    void               *arg; //回调函数参数
    struct  task      *next;
} task_t;

// 线程池结构体
typedef struct threadpool
{
    condition_t      ready; // 任务准备就绪或线程池销毁通知
    task_t    *      first; // 任务队列头指针
    task_t    *       last; // 任务队列尾指针
    int            counter; // 线程池中当前线程数
    int               idle; // 线程池中当前正在等待任务的线程
    int        max_threads; // 线程池中最大允许的线程数
    int               quit; // 销毁线程池的时候置1
} threadpool_t;

// 初始化线程池
void threadpool_init(threadpool_t *pool, int threads);

// 往线程池中添加任务
void threadpool_add_task(threadpool_t *pool, void*(*run)(void *arg), void *arg);

// 销毁线程池
void threadpool_destroy(threadpool_t *pool);



//threadpool.c
#include "threadpool.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <time.h>


void *thread_routine(void *arg)
{
    struct timespec abstime;
    int timeout;

    printf("thread 0x%x is starting\n", 
                          (int)pthread_self());



    threadpool_t *pool = (threadpool_t*)arg;
    while (1)
    {
        timeout = 0;
        condition_lock(&pool->ready);

        // 刚创建好的线程肯定是空闲的
        pool->idle++;

        //等待任务队列,如果没有任务或线程池不通知销毁,则等待
        while (pool->first == NULL && !pool->quit)
        {
            printf("thread 0x%x is waiting\n", (int)pthread_self());

            //condition_wait(&pool->ready);
            // 如果想让线程在空闲一定时间后自动销毁
            clock_gettime(CLOCK_REALTIME, &abstime);
            abstime.tv_sec += 2;
            int status = condition_timedwait(&pool->ready, &abstime);
            if (status == ETIMEDOUT)
            {
                printf("thread 0x%x is wait timed out\n", (int)pthread_self());
                timeout = 1;
                break;
            }
        }

        // 有任务或销毁通知,不空闲了
        pool->idle--;

        // 如果有任务
        if (pool->first != NULL)
        {
            // 从队列头取出任务
            task_t *t = pool->first;
            pool->first = t->next;

            // 这里要解锁,并发时以便
            // 生产者线程能够往队列中添加新任务
            // 其它消费者线程能进入等待任务
            condition_unlock(&pool->ready);
            t->run(t->arg);
            free(t);
            // 这里再把锁加回去
            condition_lock(&pool->ready);
        }

        // 如果等待到线程池销毁通知,且任务都执行完毕
        if (pool->quit && pool->first == NULL)
        {
            pool->counter--;

            // 当线程数量为0时,通知主线程销毁退出
            if (pool->counter == 0)
            {
                condition_sinal(&pool->ready);
            }
            // 跳出循环前,记得要释放锁
            condition_unlock(&pool->ready);
            break;
        }

        // 如果超时
        if (timeout && pool->first == NULL)
        {
            pool->counter--;
            // 跳出循环前,记得要释放锁
            condition_unlock(&pool->ready);
            break;
        }

        condition_unlock(&pool->ready);
    }   

    printf("thread 0x%x is exiting\n", 
                          (int)pthread_self());
    return NULL;
}

// 初始化线程池
void threadpool_init(threadpool_t *pool, int threads)
{   
    // 对线程池中的各个字 段初始化
    condition_init(&pool->ready);
    pool->first = NULL;
    pool->last  = NULL;
    pool->counter = 0;
    pool->idle    = 0;
    pool->max_threads = threads;
    pool->quit = 0;
}

// 往线程池中添加任务
void threadpool_add_task(threadpool_t *pool, void*(*run)(void *arg), void *arg)
{
    //void *(*run)(void *arg); //任务回调函数
    //void               *arg; //回调函数参数
    struct  task      *next;

    // 生成新任务
    task_t *newtask = malloc(sizeof(task_t));
    if (newtask)
    {
        newtask->run = run;
        newtask->arg = arg;
        newtask->next = NULL;
    }

    condition_lock(&pool->ready);

    // 将任务添加到队列
    if (pool->first == NULL) 
        pool->first = newtask;// 第一次添加
    else
        pool->last->next = newtask;

    pool->last = newtask;

    if (pool->idle > 0)
    {
        // 如果有等待线程,则唤醒其中一个
        condition_sinal(&pool->ready);
    }
    else if (pool->counter < pool->max_threads)
    {
        // 如果没有等待线程,且当前线程数没有超过最大阈值
        pthread_t tid;
        pthread_create(&tid, NULL, thread_routine, pool);
        pool->counter++;
    }

    condition_unlock(&pool->ready);
}

// 销毁线程池
void threadpool_destroy(threadpool_t *pool)
{

    if (pool->quit)
    {

        return;
    }
    condition_lock(&pool->ready);
    pool->quit = 1;
    if (pool->counter > 0)
    {
        if (pool->idle > 0)
        {
            condition_broadcast(&pool->ready);
        }

        // 处于执行任务状态中的线程, 不会收到广播
        // 线程池需要等待所有线程的任务执行完毕
        while (pool->counter > 0)
        {
            condition_wait(&pool->ready);
        }
    }
    condition_unlock(&pool->ready);

    condition_destroy(&pool->ready);
}

/*============================================================*/

// 使用
#include "threadpool.h"
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void* mytask(void *arg)
{
    printf("thread 0x%x is working on task %d\n", 
                          (int)pthread_self(), *(int*)arg);
    sleep(1);
    free(arg);

    return NULL;
}

int main(void)
{
    threadpool_t pool;
    threadpool_init(&pool, 3); //3个线程的线程池

    int i;
    for (i = 0; i < 10; ++i)
    { 
        int *arg = (int*)malloc(sizeof(i));
        *arg = i;
        threadpool_add_task(&pool, mytask, arg);
    }


    //sleep(15);

    threadpool_destroy(&pool);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值