C++线程池讲解及Linux环境代码示例(演示代码使用C++11之前的特性)

本文详细介绍了线程池的概念、使用原因、组成部分以及注意事项,提供了一个C++98/03标准的线程池代码示例,并强调了在实际项目中的改进点,如使用成熟线程池库和C++11特性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 线程池是什么?

线程池是一种基于多线程的并发设计模式,用来减少在应用程序中创建和销毁线程的频率。它通过维护多个线程待命,来处理多个任务,这些线程可以循环利用,以避免频繁的创建线程的开销。这些线程在创建线程池时生成,并在线程池销毁时终止。

2. 为什么要使用线程池?

使用线程池的主要优点包括:

  • 性能提高:通过重复使用现有线程减少线程创建和销毁的开销。
  • 资源控制:允许程序更好地管理资源使用,例如限制最大并发线程数,从而避免过多的线程耗尽系统资源。
  • 更简单的线程管理:线程的生命周期管理被集中,简化了编程模型。

3. 线程池的组成部分

线程池主要由以下几个部分组成:

  • 工作线程:这些是线程池中的线程,负责执行任务。
  • 任务队列:一个线程安全的队列,用于存储待处理的任务。
  • (例如互斥锁):用于控制对任务队列的并发访问。
  • 条件变量:用来阻塞线程直到有任务可执行,或通知线程任务已可执行。
  • 管理机制:负责处理线程的创建、销毁和健康状态等。

4. 使用线程池时需要注意的事项

  • 适当配置:线程池的大小应根据系统资源和需求适当配置。
  • 避免长时间任务:长时间运行的任务可能会占用所有可用线程,导致线程池饱和。
  • 异常处理:确保任务中的异常被妥善处理,避免异常影响线程池中的其他任务。
  • 线程同步:在任务中合理使用同步机制,避免死锁和资源竞争问题。

5. 一个安全的线程池代码示例(C++98/03标准)

以下是一个简单的线程池实现示例,不使用 C++11 或更高版本的特性,仅使用 POSIX 线程库。

threadpool.cpp

#include <pthread.h>
#include <queue>
#include <iostream>
#include <stdexcept>
#include <unistd.h>

class ThreadPool {
public:
    ThreadPool(size_t num_threads) : stopping(false) 
    {
        pthread_mutex_init(&lock, NULL);
        pthread_cond_init(&cond, NULL);
        for (size_t i = 0; i < num_threads; ++i) 
        {
            pthread_t worker_thread;
            pthread_create(&worker_thread, NULL, worker, this);
            workers.push_back(worker_thread);
        }
    }

    ~ThreadPool() 
    {
        pthread_mutex_lock(&lock);
        stopping = true;
        pthread_cond_broadcast(&cond);
        pthread_mutex_unlock(&lock);
        for (size_t i = 0; i < workers.size(); ++i) 
        {
            pthread_join(workers[i], NULL);
        }
        pthread_mutex_destroy(&lock);
        pthread_cond_destroy(&cond);
    }

    void enqueue(void (*task)()) 
    {
        pthread_mutex_lock(&lock);
        tasks.push(task);
        pthread_cond_signal(&cond);
        pthread_mutex_unlock(&lock);
    }

private:
    static void* worker(void* arg) 
    {
        ThreadPool* pool = (ThreadPool*)arg;
        while (true) {
            pthread_mutex_lock(&pool->lock);
            while (pool->tasks.empty() && !pool->stopping) {
                pthread_cond_wait(&pool->cond, &pool->lock);
            }
            if (pool->stopping && pool->tasks.empty()) {
                pthread_mutex_unlock(&pool->lock);
                break;
            }

            /*
                void: 表示函数没有返回值。
                (*task): task 是一个指针,* 表明这是一个指向函数的指针。
                (): 表示函数不接受任何参数。
            */
            void (*task)() = pool->tasks.front();
            pool->tasks.pop();
            pthread_mutex_unlock(&pool->lock);
            task();  // 执行任务
        }
        return 0;
    }

private:
    pthread_mutex_t lock;
    pthread_cond_t cond;
    std::queue<void (*)()> tasks;
    std::vector<pthread_t> workers;
    bool stopping;
};

void taskFunction() {
    std::cout << "Executing Task" << std::endl;
}

int main() {
    ThreadPool pool(4);
    pool.enqueue(taskFunction);
    pool.enqueue(taskFunction);
    pool.enqueue(taskFunction);
    pool.enqueue(taskFunction);
    sleep(1);  // 等待任务完成
    return 0;
}

6. 代码解释

这段代码实现了一个基本的线程池,其中包含:

  • 一个任务队列和一组工作线程。
  • 使用互斥锁和条件变量来控制对任务队列的访问和线程的同步。
  • 工作线程从队列中取出任务并执行,当没有任务时会等待。
  • 析构函数中停止所有工作线程,并清理 POSIX 线程相关资源。

7. 编译

g++ -o threadpool threadpool.cpp -lpthread

8. 输出代码运行结果

./threadpool

程序创建了一个线程池并提交了四个任务,每个任务简单地输出 “Executing Task”。由于使用了 sleep(1),主线程会等待足够的时间让所有任务执行完毕。可以看到输出中四次 “Executing Task” 的结果。

注意

这个实现较为简单,主要用于演示目的。在生产环境中,建议使用成熟的线程池库,如 Boost.Asio 的线程池功能,或者升级到支持 C++11 或更高版本的编译器,使用 std::thread 和相关的高级特性。
后面会更新C++11版本的线程池示例)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Warren++

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值