首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

linux c 线程池实现

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池可以有效地控制系统中并发线程的数量,避免大量线程之间的切换所带来的性能开销。

基础概念

  1. 线程池(Thread Pool):预先创建一定数量的线程,当有任务到来时,从线程池中分配一个空闲线程来执行任务,执行完毕后线程并不销毁,而是回到线程池中等待下一个任务。
  2. 工作队列(Work Queue):用于存储待处理的任务。
  3. 线程工厂(Thread Factory):用于创建新线程。
  4. 拒绝策略(Rejection Policy):当线程池和工作队列都满时,新任务的处理策略。

优势

  • 降低资源消耗:通过重用已创建的线程,减少在创建和销毁线程上花费的时间以及系统资源的开销。
  • 提高响应速度:任务到达时,任务可以不需要等待线程创建就能立即执行。
  • 提高线程的可管理性:线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一分配、调优和监控。

类型

  • Fixed Thread Pool:线程数量固定的线程池。
  • Cached Thread Pool:线程数量不固定,根据需要创建新线程,空闲线程会被回收。
  • Scheduled Thread Pool:支持定时及周期性任务执行的线程池。
  • Single Thread Executor:只有一个线程的线程池,保证任务顺序执行。

应用场景

  • Web服务器:处理客户端请求。
  • 数据库连接池:管理数据库连接。
  • 并发计算:如科学计算中的并行处理。
  • 后台任务处理:如定时任务、批处理作业。

实现示例(Linux C语言)

代码语言:txt
复制
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>

typedef struct {
    void (*function)(void *);
    void *argument;
} task_t;

typedef struct {
    task_t *tasks;
    int front;
    int rear;
    int count;
    int capacity;
    pthread_mutex_t lock;
    pthread_cond_t not_empty;
    pthread_cond_t not_full;
} thread_pool_t;

void *worker(void *arg) {
    thread_pool_t *pool = (thread_pool_t *)arg;
    while (1) {
        pthread_mutex_lock(&pool->lock);
        while (pool->count == 0) {
            pthread_cond_wait(&pool->not_empty, &pool->lock);
        }
        task_t task = pool->tasks[pool->front++];
        pool->front %= pool->capacity;
        pool->count--;
        pthread_cond_signal(&pool->not_full);
        pthread_mutex_unlock(&pool->lock);

        task.function(task.argument);
    }
    return NULL;
}

void thread_pool_init(thread_pool_t *pool, int num_threads, int capacity) {
    pool->tasks = (task_t *)malloc(sizeof(task_t) * capacity);
    pool->front = pool->rear = pool->count = 0;
    pool->capacity = capacity;
    pthread_mutex_init(&pool->lock, NULL);
    pthread_cond_init(&pool->not_empty, NULL);
    pthread_cond_init(&pool->not_full, NULL);

    for (int i = 0; i < num_threads; i++) {
        pthread_t thread;
        pthread_create(&thread, NULL, worker, pool);
        pthread_detach(thread);
    }
}

void thread_pool_add_task(thread_pool_t *pool, void (*function)(void *), void *argument) {
    pthread_mutex_lock(&pool->lock);
    while (pool->count == pool->capacity) {
        pthread_cond_wait(&pool->not_full, &pool->lock);
    }
    pool->tasks[pool->rear].function = function;
    pool->tasks[pool->rear].argument = argument;
    pool->rear = (pool->rear + 1) % pool->capacity;
    pool->count++;
    pthread_cond_signal(&pool->not_empty);
    pthread_mutex_unlock(&pool->lock);
}

void example_task(void *arg) {
    int *num = (int *)arg;
    printf("Task %d is running.\n", *num);
}

int main() {
    thread_pool_t pool;
    thread_pool_init(&pool, 4, 10);

    for (int i = 0; i < 10; i++) {
        int *num = (int *)malloc(sizeof(int));
        *num = i;
        thread_pool_add_task(&pool, example_task, num);
    }

    sleep(5); // Wait for tasks to complete
    return 0;
}

可能遇到的问题及解决方法

  1. 线程安全问题:多个线程同时访问共享资源可能导致数据不一致。使用互斥锁(mutex)和条件变量(condition variable)来保护共享资源。
  2. 死锁:线程相互等待对方释放资源。确保加锁顺序一致,避免循环等待。
  3. 资源耗尽:线程池过大可能导致系统资源耗尽。合理设置线程池大小和工作队列容量。
  4. 任务拒绝:当线程池满且工作队列也满时,新任务可能被拒绝。实现合适的拒绝策略,如丢弃任务、抛出异常或由调用者线程执行。
  5. 性能瓶颈:线程切换开销过大。优化任务粒度,减少线程间通信,使用无锁数据结构等。

通过合理设计和实现线程池,可以有效提升多线程程序的性能和稳定性。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

C++线程池实现_java线程池状态

在计算机程序中,线程是一种很重要的资源,使用的恰当可以极大的提高程序的效率,也就是多线程的使用,但是多线程会让应用程序变得异常复杂,会占用大量的系统资源。...在这种情况下,多线程变得不太合适了,那么什么机制适用于这种情况下呢,这就是线程池。...通常情况下,应用程序中采用异步调用函数的形式来实现多任务,在windows中,系统提供了QueueUserWorkItem函数实现异步调用,这个函数相当于在线程池中建立多个用户工作项目,跟普通线程机制一样...,线程池也有线程的同步等机制。...下面实现了一个简单的线程池程序,没有什么大的功能,可以看到线程池的用法。

78410
  • C语言实现线程池

    C语言标准库中并没有提供线程池的实现,线程池需要手搓 实现线程池的基本思路是:先创建几个固定的线程,让每个线程运行起来,然后通过互斥锁和条件变量使得每个线程进入等待状态,当需要分派线程时,改变条件变量,...同时实现了一个队列来存储需要执行的任务。 Task结构体用于表示线程池需要执行的任务,包括属性函数指针和函数参数。...,包括内嵌实现的队列,用的是循环索引数组模拟实现的队列,互斥锁和条件变量,固定大小的线程组,还有一个是否销毁线程池的标记。...int shutdown; // 是否销毁线程池 } ThreadPool; 初始化线程池,创建POOLSIZE个线程,创建日志文件,初始化互斥锁和条件变量。...,设置线程池销毁标记,等待所有线程结束后释放线程内存,并销毁互斥锁和条件变量。

    50610

    Linux C下线程池的使用

    线程池本质上也是一个数据结构,需要一个结构体去描述它: struct pthread_pool //线程池的实现 { //一般会有如下成员 //互斥锁,用来保护这个“任务队列” pthread_mutex_t...任务结点类型的指针,指向下一个任务 struct task * next; }; 线程池框架代码如下,功能自填: 操作线程池所需要的函数接口:pthread_pool.c 、pthread_pool.h...把“线程池”想象成一个外包公司,你需要去完成的就是操作线程池所提供的函数接口。...pthread_pool.c #include "pthread_pool.h" /* init_pool: 线程池初始化函数,初始化指定的线程池中有thread_num个初始线程 @pool:指针...任务结点类型的指针,指向下一个任务 struct task * next; }; struct pthread_pool //线程池的实现 { //一般会有如下成员 //互斥锁,用来保护这个“

    1.8K50

    Linux下精简线程池的实现

    线程清理函数 3. 结构 4. 遇到的问题 5. 代码 6. 待解决 7. 其他 8. 参考 在Linux下使用C++调用pthread API实现的一个线程池。...简介 这个线程池是在学习完《Linux/UNIX系统编程手册》中线程相关知识后用来练手的小项目,线程相关函数都是直接调用Linux的API,并且使用了C++中的queue和vector。...待学习:使用gdb调试多线程线程的查看以及利用gdb调试多线程 阅读jdk里的线程池源码 参考 线程数究竟设多少合理 C++并发实战17:线程安全的stack和queue linyacool WebServer...中的线程池 用C++写线程池是怎样一种体验?...基于c++11的100行实现简单线程池 使用C++11实现线程池的两种方法 欢迎与我分享你的看法。 转载请注明出处:http://taowusheng.cn/

    1.8K30

    C++ 线程池的实现(上)

    引言 最近工作开始使用C++,于是想用C++实现一个线程池。这里就分两篇文章来记录一下实现的过程,本篇主要为理论篇,具体的实践篇,等代码功能稳定以后再总结。 2....简介 本部分从线程池作用到线程池的原理介绍。想要实现具体的线程池,需要先知道线程池有什么作用,然后再去学习他的原理,最终用代码实现出来。...在线程池中只存在几个固定的线程,由线程池来维护,等待调度器派发已存在空闲的线程去执行对应的任务。 由此,便实现了线程的一次创建多次使用的功能,从而避免了短时间内的任务时创建与销毁线程的代价。...线程池不仅能保护资源的充分利用,还能保证不被过分调度。 线程池的原理 线程池的在初始化时,会先创建固定数量的线程;具体的任务会放在任务队列中,类似于生产者-消费者概念。...如此反复便实现了,多个任务并发的执行。 ? 线程池原理.png 3 总结 本篇文章简单记录一下线程池的作用及原理,后续文章会记录具体的代码实现。

    1.5K20

    Linux多线程【线程池】

    ,短时间内,在服务器创建大量线程会使得内存达到极限,造成出错,可以使用 线程池 规避问题 2.线程池的实现 2.1.线程池_V1(朴素版) 「朴素版」:实现最基本的线程池功能,直接使用系统提供的接口 所谓朴素版就是不加任何优化设计...,只实现 线程池 最基础的功能,便于理解 线程池 创建 ThreadPool_v1.hpp 头文件 将 线程池 实现为一个类,提供接口供外部调用 首先要明白 线程池 的两大核心:一批线程 与 任务队列...<< std::endl; } }; } 结果也是正常的 所以如果当前的生产环境所支持的 C++ 版本为 C++11 及以后,在实现 懒汉模式 时可以选择这种简便的方式,是非常不错的...多线程【线程池】的全部内容了,作为多线程篇章的收官之作,首先学习了池化技术,了解了线程池的特性,然后又分别实现了四个版本的线程池,循序渐进,最终得到了单例版的线程池,得益于模板,此线程池可以轻松应用于其他场景中...===== :> 【软硬链接与动静态库】、【深入理解文件系统】、【模拟实现C语言文件流】、【重定向及缓冲区理解】、【文件理解与操作】 Linux进程控制 ===== :> 【简易版bash】、【进程程序替换

    52840

    初识Linux · 线程池

    前言: 前文我们介绍了基于线程同步和互斥两种关系的一种模型->生产消费模型,那么之前在学习进程的时候我们已经编写过了进程池,同理,学习线程的时候我们也要编写线程池。...那么对于线程池的编写,我们也不废话,直接进入主题。...thread pool成员变量分析 对于一个线程池来说,锁和条件变量肯定是少不了的,对于线程处理的任务来说,也需要一个队列用来表示任务队列,我们可以用环形队列也可以使用阻塞队列,这里我们就使用阻塞队列好了...那么线程池存在那么多的线程,谁工作了谁休眠了总得有个数吧?所以我们不妨设置一个sleep_thread_num和一个thread_num,用来表示线程池中线程的情况。...其次是线程池有没有running起来,刚构造线程池的时候连线程都没有创建呢,也就不可能将参数设置为true了。 接下来的函数就是,线程池构造好了,得对任务队列初始化吧?

    6110

    C++创建线程池_windows线程池iocp

    c++简单线程池实现 线程池,简单来说就是有一堆已经创建好的线程(最大数目一定),初始时他们都处于空闲状态,当有新的任务进来,从线程池中取出一个空闲的线程处理任务,然后当任务处理完成之后,该线程被重新放回到线程池中...我们为什么要使用线程池呢?...线程池适合场合: 事实上,线程池并不是万能的。它有其特定的使用场合。线程池致力于减少线程本身的开销对应用所产生的影响,这是有前提的,前提就是线程本身开销与线程执行任务相比不可忽略。...如果线程本身的开销相对于线程任务执行开销而言是可以忽略不计的,那么此时线程池所带来的好处是不明显的,比如对于FTP服务器以及Telnet服务器,通常传送文件的时间较长,开销较大,那么此时,我们采用线程池未必是理想的方法...总之线程池通常适合下面的几个场合: (1) 单位时间内处理任务频繁而且任务处理时间短 (2) 对实时性要求较高。如果接受到任务后在创建线程,可能满足不了实时要求,因此必须采用线程池进行预创建。

    92230

    C++11多线程编程(六)——线程池的实现

    一、为何需要线程池 那么为什么我们需要线程池技术呢?多线程编程用的好好的,干嘛还要引入线程池这个东西呢?引入一个新的技术肯定不是为了装逼,肯定是为了解决某个问题的,而服务端一般都是效率问题。...二、C++中的线程池 但是让人遗憾的是,C++并没有在语言级别上支持线程池技术,总感觉C++委员会对多线程的支持像是犹抱琵琶半遮面的羞羞女一样,无法完全的放开。...虽然无法从语言级别上支持,但是我们可以利用条件变量和互斥锁自己实现一个线程池。...这里就不得不啰嗦几句,条件变量和互斥锁就像两把利剑,几乎可以实现多线程技术中的大部分问题,不管是生产消费者模型,还是线程池,亦或是信号量,所以我们必须好好掌握好这两个工具。...看过我之前写的《生产消费者模型之条件变量》的朋友对以上代码有点熟悉,没错,线程池的实现就有点像是生产消费者模型,append()就像是生产者,不断的将任务放入队列,run()函数就像消费者,不断的从任务队列中取出任务来处理

    65810

    http线程池的设计与实现(c++)

    http线程池的主要用途是异步处理使用无状态短连接的http请求,在传输层通信基于tcp协议和应用层基于http协议的基础上,达到c++服务器与web服务器通信的目的。...设计上: (1)服务器启动时,初始化配置数量的线程(形成被动连接线程池)。每个线程会生成epoll描述符。 (2)主线程生成监听socket,绑定端口。...跟单业务线程的场景不同的是,http线程池的线程之间尽量减少数据共享(实在需要缓存在内存则加锁),每个线程又可以作为客户端短时间阻塞向其他服务器请求数据。...http线程池代码如下:(大致上http线程池的思路可以看得出来。主线程接收连接对象和连接对象接收数据并没有在这里展现实现过程。...接收成功、失败、超时都需要移除连接对象(epoll描述符注销连接socket、关闭socket、移出和销毁连接对象),因为是短连接) 线程池头文件 /** * \brief 定义实现轻量级(lightweight

    1.7K30

    c++11 线程池实现以及示例

    https://blog.csdn.net/haluoluo211/article/details/79659864 线程池的使用在工作中非常普遍,对于java,python而言线程池使用还是比较方便...去年年底由于工作需要,用c++搭建一套工程代码,需要使用线程池,但是C++中并没有现有的线程池,为了快速开发,以及代码的稳定还是google在github上面找到了一个不错的C++11实现的版本,然后做了一点修改...通过这一个线程池的实现,收获如下: 1. 更加深入的理解了线程池 2....,阻塞等待请求,或者事件(例如epoll事件),然后将数据以及handle压入线程池处理,这样无需等待handle函数处理完,即可等待下一次的请求或者事件(相当于是异步)。...//创建一个还有5个线程的线程池 ThreadPool tp(5); while(true){ // 阻塞的等待http的请求数据data data =

    5.5K51

    【Linux线程】从零到一:掌握Linux线程池的设计与实现

    而在Linux这一广泛应用的操作系统中,线程池作为一种高效管理线程资源的机制,更是成为了众多开发者关注的焦点 线程池通过预先创建并维护一定数量的线程,使得线程可以被重复利用,从而避免了频繁创建和销毁线程所带来的性能损耗...在Linux环境下,线程池的应用更是广泛,无论是服务器端的并发处理,还是客户端的响应速度提升,都离不开线程池的助力 在本文中,我们将从线程池的基本概念入手,逐步深入到线程池的实现细节。...我们会结合Linux操作系统的特点,为大家讲解如何在Linux环境下构建和管理线程池。...同时,我们还将分享一些在实际项目中应用线程池的经验和教训,帮助大家更好地理解和运用线程池技术 希望本文能够成为大家学习Linux线程池路上的得力助手,助力大家在多线程并发编程的道路上越走越远。 1....突发性大量客户请求,在没有线程池情况下,将产生大量线程,虽然理论上大部分操作系统线程数目最大值不是问题,短时间内产生大量线程可能使内存到达极限,出现错误 在我们模拟实现线程池的时候,我们会用到我们前面自己模拟实现的一些文件

    15710

    【C++】开源:ThreadPoll线程池实现与使用

    线程池介绍 线程池是一种线程管理的抽象概念,它主要用于优化多线程应用程序的性能和资源利用。在多线程编程中,创建和销毁线程是一个开销较大的操作。...当任务提交到线程池时,它们被放置在任务队列中等待执行。 2.线程池管理器(Thread Pool Manager):负责创建、管理和调度线程池中的线程。...使用线程池的好处包括: 提高性能:线程池可以减少线程的创建和销毁次数,避免了频繁的上下文切换,提高了多线程程序的性能和响应速度。...线程池实现1-单头文件 Github项目:https://github.com/progschj/ThreadPool threadpoll.h #ifndef THREAD_POOL_H #define...线程池实现2-较复杂 Github项目:https://github.com/volute24/ThreadPoll // main.cpp #include "threadpool.h" #include

    45910
    领券