一、线程池的好处

如果任务的数量一开始不确定,我们该如何开辟线程?如果来一个任务开辟一个线程,任务结束之后又销毁线程,那么整体的效率会很低,大多数时间都在产生和销毁线程,该如何摆脱这种困境?

线程池的概念孕育而生,我们可以一次产生4个线程,它们组成一个线程池,相当于食堂的打菜大妈;接着会有一波任务接连过来,这些线程便依次完成这些任务,如果暂时没有任务,它们也不销毁,继续等待,直到设定的一定之间后,才销毁线程池。

线程池能够大大提高任务执行的效率。

二、线程池实例

如果从头开始写线程池,会非常复杂,目前我也没这个水平。花了很大功夫才找到Github上一个开源的线程池代码,并且用实例跑通了这个线程池,效果还是不错的。

这个线程池需要两个文件thpool.c和thpool.h。还是求和的例子,我们用线程池来实现:线程池有四个线程,1亿个元素分成40个任务,依次加入线程池,然后将40个结果再求和。

// gcc example3.c thpool.c -lpthread -D THREAD_DEBUG
// 正式运行时不需要加 -D THREAD_DEBUG
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include "thpool.h"

const int S = 100000000;
int* arr;

typedef struct{
    int first;
    int last;
    int result;
}MY_ARGS;


void mysum(void *args){
    int i;
    int s=0;
    MY_ARGS* my_args = (MY_ARGS*) args;
    int first = my_args->first;
    int last = my_args->last;

    for(i=first;i<last;i++){
        s = s + arr[i];
    }
    my_args -> result = s;
}

int main(){

    int i;
    arr = malloc(sizeof(int) * S);
    //1.数据准备
    for(i=0;i<S;i++){
        if(i%2==0)
            arr[i]=-i;
        else
            arr[i]=i;
    }
    //2.初始化线程池,4个线程
    threadpool thpool = thpool_init(4);
    int task_num = 40;
    int mid = S/task_num;
    //3.设置任务队列,并添加至线程池
    MY_ARGS args[task_num];
    for (i=0; i<task_num; i++){
        args[i].first=i*mid;
        args[i].last=(i+1)*mid;
        args[i].result=0;
        thpool_add_work(thpool, mysum, &args[i]);
    };
    //4.等待线程池任务结束并销毁
    thpool_wait(thpool);
    thpool_destroy(thpool);
    //5.结果合计及输出
    int sum=0;
    for (i=0;i<task_num;i++){
        sum +=args[i].result;
    }
    printf("%d \n", sum);
    return 0;
}

注意这里的mysum函数与pthread中有些不同,void没有加*,也没有return。我们可以自己修改mysum函数来完成不同的任务。

更多实例在我gitee:thread_pool

标签: 算法, C++, 线程池

添加新评论