线程池

线程池:

当需要大量的并且是相对短暂的线程,我们需要创建线程池。

计算密集型: 线程池中的线程个数应该等于(=) CPU。
IO密集型: 线程池中的线程个数大于(>)CPU。
目的:

能够动态的增加线程池中的线程个数;
动态的销毁线程池中的线程.

本质:

是一个生产者消费者模型,来了任务放到任务队列,线程池中的线程从任务队列中拿任务,然后进行处理。

这里写图片描述


代码实现:

Makefile test.c threadpool.h threadpool.c condition.c condition.h

Makefile :
.PHONY: clean

OBJETS = threadpool.o \
        condition.o \
        test.o 
CC=gcc

all : test

test : $(OBJETS)
    $(CC) $^ -o $@ -lpthread -lrt

%.O : %.c
    gcc -c $< -o $@

clean:
    rm -rf $(OBJETS)

conditon.h:
#ifndef __CONDITION_H__
#define __CONDITION_H__

#include <pthread.h>
#include <time.h>

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

int condition_init(condition_t *pc);
int condition_destroy(condition_t *pc);

int condition_lock(condition_t *pc);
int condition_unlock(condition_t *pc);

int condition_wait(condition_t *pc);
int condition_timedwait(condition_t *pc, struct timespec *abstime);

int condition_signal(condition_t *pc);
int condition_boardcast(condition_t *pc);

#endif //__CONDITION_H__

condition.c:
#include "condition.h"

int condition_init(condition_t *pc)
{
    int ret = 0;

    do {
        ret = pthread_cond_init(&pc->pcond, NULL);
        if (ret != 0 ) break;
        ret = pthread_mutex_init(&pc->pmutex, NULL);
    } while ( 0 );

    return ret;
}

int condition_destroy(condition_t *pc)
{
    int ret = 0;
    do {
        ret = pthread_cond_destroy(&pc->pcond);
        if (ret != 0 ) break;
        ret = pthread_mutex_destroy(&pc->pmutex);
    } while ( 0 );

    return 0;
}

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

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

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

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

int condition_signal(condition_t *pc)
{
    return pthread_cond_signal(&pc->pcond);
}

int condition_boardcast(condition_t *pc)
{
    return pthread_cond_broadcast(&pc->pcond);
}

threadpool.h :
#ifndef __THREADPOOL_H__
#define __THREADPOOL_H__

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include "condition.h"

// 任务节点
typedef struct node {
    void *(*pfun)(void *); // 回调函数
    void *arg; // 回调函数的参数
    struct node *next;
}node_t;

// 代表线程池
typedef struct threadpool {
    condition_t ready;      // 控制同步和互斥
    node_t *first;          // 队头指针
    node_t *tail;           // 队尾指针
    int counter;            // 线程池中当前有多少个线程 
    int idle;               // 空闲线程个数
    int max_thread;         // 最多可以创建多少个线程
    int quit;               // 为1,代表要销毁线程池
}threadpool_t;

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

// 添加任务
void threadpool_add(threadpool_t *pool, void *(*pf)(void*), void *arg);

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

#endif //  __THREADPOOL_H__

threadpool.c :
#include "threadpool.h"
#include <errno.h>

// 初始化线程池
void threadpool_init(threadpool_t *pool, int max_thread)
{
    condition_init(&pool->ready);
    pool->tail       = NULL;
    pool->idle       = 0;
    pool->quit       = 0;
    pool->first      = NULL;
    pool->counter    = 0;
    pool->max_thread = max_thread;
}

static void *route(void *arg)
{
    threadpool_t *pool = (threadpool_t*)arg;
    int timeout = 0;

    while ( 1 ) {
        timeout = 0;
        condition_lock(&pool->ready);       
        pool->idle++; // 还没开始工作,是一个空闲线程
        while ( pool->first == NULL && pool->quit==0) {
            struct timespec abs;
            clock_gettime(CLOCK_REALTIME,  &abs);
            abs.tv_sec += 2;
            int ret = condition_timedwait(&pool->ready, &abs);
            if ( ret == ETIMEDOUT ) {
                timeout = 1;
                break;
            }
        }
        pool->idle--; // 开始工作,空闲线程个数减少

        // 处理任务
        if ( pool->first != NULL ) {
            node_t *p = pool->first;
            pool->first = p->next;
            // 防止回调任务执行时间太长,导致别的线程没法执行
            condition_unlock(&pool->ready);     
            (p->pfun)(p->arg);
            free(p);
            condition_lock(&pool->ready);       
        }

        // 处理超时
        if ( timeout == 1 && pool->first == NULL ) {
            printf("%#X thread time out exit\n", pthread_self());
            pool->counter--;
            condition_unlock(&pool->ready);     
            break;
        }

        // 收到退出通知
        if ( pool->quit == 1 && pool->first == NULL ) {
            printf("%#X thread quit\n", pthread_self());
            pool->counter--;
            if ( pool->counter == 0 )
                condition_signal(&pool->ready);
            condition_unlock(&pool->ready);
            break;
        }

        condition_unlock(&pool->ready);     
    }
}

// 添加任务
void threadpool_add(threadpool_t *pool, void *(*pf)(void*), void *arg)
{
    // 生成任务节点
    node_t *pnode = (node_t*)malloc(sizeof(node_t));
    memset(pnode, 0x00, sizeof(node_t));
    pnode->pfun = pf; 
    pnode->arg  = arg;
    pnode->next = NULL;

    // 修改多个线程都可能修改的数据
    condition_lock(&pool->ready);

    // 放入任务队列
    if ( pool->first == NULL ) 
        pool->first = pnode;
    else
        pool->tail->next = pnode;
    pool->tail = pnode;

    // 如果池中有空闲线程,唤醒它执行任务
    if ( pool->idle > 0 ) {
        condition_signal(&pool->ready);
    } 
    // 如果没有空闲线程,并且当前线程个数小于最大值,创建新线程来执行任务
    else if ( pool->counter < pool->max_thread ) {
        pthread_t tid;
        pthread_create(&tid, NULL, route, (void*)pool);
        pthread_detach(tid);
        pool->counter ++; // 线程池中线程个数增加
    }

    condition_unlock(&pool->ready);
}

// 销毁线程池
void threadpool_destroy(threadpool_t *pool)
{
    if ( pool->quit == 1 )
        return;

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

    //  等待没有收到销毁广播,这些线程都是正在执行任务。
    while ( pool->counter > 0 ) {
        condition_wait(&pool->ready);
    }

    condition_unlock(&pool->ready);
}

test.c :
#include "threadpool.h"

void *mytask( void *arg)
{
    int id = *(int*)arg;
    free(arg);
    printf("%#X thread execute %d\n", pthread_self(), id);
    sleep(1);
}

int main( void )
{
    threadpool_t pool;

    threadpool_init(&pool, 4);

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

    threadpool_destroy(&pool);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值