第12章 线程控制-线程池

线程池的示意图,类似于生产者消费者模式

这里写图片描述

thread_main.cpp

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include "thread_pool.h"

void *func(void *arg)
{
    printf("thread %d\n", *(int*)arg);
    return NULL;
}

int main(int arg, char **argv)
{
    printf("创建线程池。");
    if (tpool_create(5) != 0) {
        printf("tpool_create failed\n");
        exit(1);
    }
    int n = 20;
    int* id = (int*)malloc(sizeof(int) * n);
    for (int i = 0; i < n; ++i) 
    {
        id[i] = i;
        tpool_add_work(func, id + i); 
    }
    free(id);
    sleep(2);
    tpool_destroy();
    return 0;
}

thread_pool.h

#ifndef _THREAD_POOL_
#define _THREAD_POOL_

#include <pthread.h>

/* 要执行的任务链表 */
typedef struct tpool_work {
    void*               (*routine)(void*);       /* 任务函数 */
    void                *arg;                    /* 传入任务函数的参数 */
    struct tpool_work   *next;                    
}tpool_work_t;

typedef struct tpool {
    int             shutdown;                    /* 线程池是否销毁 */
    int             max_thr_num;                /* 最大线程数 */
    pthread_t       *thr_id;                    /* 线程ID数组 */
    tpool_work_t    *queue_head;                /* 线程链表 */
    pthread_mutex_t queue_lock;                    
    pthread_cond_t  queue_ready;    
}tpool_t;

/*
 * @brief     创建线程池 
 * @param     max_thr_num 最大线程数
 * @return     0: 成功 其他: 失败  
 */
int tpool_create(int max_thr_num);

/*
 * @brief     销毁线程池 
 */
void tpool_destroy();

/*
 * @brief     向线程池中添加任务
 * @param    routine 任务函数指针
 * @param     arg 任务函数参数
 * @return     0: 成功 其他:失败 
 */
int tpool_add_work(void*(*routine)(void*), void *arg);
void tpool_destroy(); 
#endif

thread_pool.cpp

#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include "thread_pool.h"
static tpool_t *tpool = NULL;
/* 工作者线程函数, 从任务链表中取出任务并执行 */
static void* thread_routine(void *arg)
{
    tpool_work_t *work;
    while(1) {
        /* 如果线程池没有被销毁且没有任务要执行,则等待 */
        pthread_mutex_lock(&tpool->queue_lock);
        while(!tpool->queue_head && !tpool->shutdown) {
            pthread_cond_wait(&tpool->queue_ready, &tpool->queue_lock);
        }
        if (tpool->shutdown) {
            pthread_mutex_unlock(&tpool->queue_lock);
            pthread_exit(NULL);
        }
        work = tpool->queue_head;
        tpool->queue_head = tpool->queue_head->next;
        pthread_mutex_unlock(&tpool->queue_lock);

        work->routine(work->arg);
        free(work);
    }
    return NULL;
}
/*
 * 创建线程池
 */
int tpool_create(int max_thr_num)
{
    int i;
    tpool = (tpool_t*)calloc(1, sizeof(tpool_t));
    if (!tpool) {
        printf("%s: calloc failed\n", __FUNCTION__);
        exit(1);
    }
    /* 初始化 */
    tpool->max_thr_num = max_thr_num;
    tpool->shutdown = 0;
    tpool->queue_head = NULL;
    if (pthread_mutex_init(&tpool->queue_lock, NULL) !=0) {
        printf("%s: pthread_mutex_init failed, errno:%d, error:%s\n",
            __FUNCTION__, errno, strerror(errno));
        exit(1);
    }
    if (pthread_cond_init(&tpool->queue_ready, NULL) !=0 ) {
        printf("%s: pthread_cond_init failed, errno:%d, error:%s\n",
            __FUNCTION__, errno, strerror(errno));
        exit(1);
    }
    /* 创建工作者线程 */
    tpool->thr_id = (pthread_t*)calloc(max_thr_num, sizeof(pthread_t));
    if (!tpool->thr_id) {
        printf("%s: calloc failed\n", __FUNCTION__);
        exit(1);
    }
    for (i = 0; i < max_thr_num; ++i) {
        if (pthread_create(&tpool->thr_id[i], NULL, thread_routine, NULL) != 0){
            printf("%s:pthread_create failed, errno:%d, error:%s\n", __FUNCTION__,
                errno, strerror(errno));
            exit(1);
        }
    }
    return 0;
}

/* 销毁线程池 */
void tpool_destroy()
{
    int i;
    tpool_work_t *member;
    if (tpool->shutdown) {
        return;
    }
    tpool->shutdown = 1;
    /* 通知所有正在等待的线程 */
    pthread_mutex_lock(&tpool->queue_lock);
    pthread_cond_broadcast(&tpool->queue_ready);
    pthread_mutex_unlock(&tpool->queue_lock);
    for (i = 0; i < tpool->max_thr_num; ++i) {
        pthread_join(tpool->thr_id[i], NULL);
    }
    free(tpool->thr_id);
    while(tpool->queue_head) {
        member = tpool->queue_head;
        tpool->queue_head = tpool->queue_head->next;
        free(member);
    }
    pthread_mutex_destroy(&tpool->queue_lock);
    pthread_cond_destroy(&tpool->queue_ready);
    free(tpool);
}

/* 向线程池添加任务 */
int tpool_add_work(void*(*routine)(void*), void *arg)
{
    tpool_work_t *work, *member;

    if (!routine){
        printf("%s:Invalid argument\n", __FUNCTION__);
        return -1;
    }
    work = (tpool_work_t*)malloc(sizeof(tpool_work_t));
    if (!work) {
        printf("%s:malloc failed\n", __FUNCTION__);
        return -1;
    }
    work->routine = routine;
    work->arg = arg;
    work->next = NULL;
    pthread_mutex_lock(&tpool->queue_lock);
    member = tpool->queue_head;
    if (!member) {
        tpool->queue_head = work;
    } else {
        while(member->next) {
            member = member->next;
        }
        member->next = work;
    }
    /* 通知工作者线程,有新任务添加 */
    pthread_cond_signal(&tpool->queue_ready);
    pthread_mutex_unlock(&tpool->queue_lock);
    return 0;
}

Makefile

# set CPUS for Linux or FreeBSD
PLATFORM := $(shell uname)
CPUS := $(strip $(if $(shell echo $(PLATFORM)|grep Linux),\
    $(shell cat /proc/cpuinfo|grep -c processor),\
    $(shell sysctl -a | egrep -i 'hw.ncpu' | cut -d: -f2)))
CC := gcc
CXX := g++
DEBUG := -D_DEBUG
DEBUG := -DNDEBUG -O3
CXXFLAGS := -g $(DEBUG) -fPIC  -MMD -Wcast-qual -Wcast-align \
    -Wwrite-strings -Wsign-compare -Winvalid-pch -fms-extensions \
    -Wfloat-equal -Wextra -Wall -Wno-unused-parameter \
    -Wno-unused-function -Wunused-variable -Wunused-value \
    -Woverloaded-virtual -Wsign-promo -fno-gnu-keywords -pipe \
    -I/usr/local/include \
    -I/home/s/include \
    -I/home/cloud/zhongchao/.local/token/include \
    -I/home/cloud/zhongchao/.local/token/qmodule/qcommon-1.0.1/include \
    -I/home/cloud/zhongchao/.local/token/qmodule/segment-2.2.0/include \
    -I/home/cloud/zhongchao/.local/token/qmodule/transcode-1.0.0/include \
    -I.
LDFLAGS := -L.. \
    -L/usr/local/lib \
    -L/usr/lib64/ \
    -L/home/s/lib \
    -L/home/cloud/zhongchao/.local/token/lib \
    -L./lib \
    -lpthread
ifeq ($(PLATFORM), Linux)
RPATH := -Wl,-rpath
else
RPATH := -rpath
endif
RTFLAGS := \
    $(RPATH)=.. \
    $(RPATH)=/home/s/lib\
    $(RPATH)=/usr/local/lib

SRCS := $(wildcard *.cpp)
OBJS := $(patsubst %.cpp, %.o, $(SRCS))
DEPS := $(patsubst %.o, %.d, $(OBJS))
thread_main : thread_main.o thread_pool.o
    $(CXX) $^ $(LDFLAGS) $(RTFLAGS) $(libs) -o $@
$(OBJS) : %.o : %.cpp
    $(CC) -c $(CXXFLAGS) $< -o $@
clean:
    rm -rf *.d *.o core.* *.out $(TARGET)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值