1. 简介

本文首先介绍 Boost.Asio 提供的线程池的使用,然后再手动实现一个线程池。

2. Boost.Asio 线程池

下载:https://sourceforge.net/proje...

VS 中使用:项目 - 属性 - VC目录 - 包含目录,添加 YourPath\asio-1.18.2\include

官方文档:https://www.boost.org/doc/lib...

#include <iostream>
#include <atomic>
#include <asio.hpp>

using namespace std::literals;

static std::atomic_uint32_t count = 0;

int main()
{
    // 两个线程
    asio::thread_pool pool(2);

    auto work = []()
    {
        std::this_thread::sleep_for(1ns);
        count++;
    };

    int n = 1000;
    for (int i = 0; i < n; i++)
    {
        // 提交任务
        asio::post(pool, work);
    }
    
    // 等待所有线程执行完成
    pool.join();

    std::cout << "count = " << count << '\n';
}
count = 1000

其他操作:

void stop();

如果可以的话,立马终止线程,还未被执行的任务可能将不会被执行.

3. 自定义线程池实现

实现思路:

  • 维护一个任务队列,其中保存用户提交的任务;
  • 创建一个线程集合,然后令每个线程去轮询任务队列,从任务队列中提取任务并执行.

ThreadPool.h

#ifndef THREADPOOL_H
#define THREADPOOL_H

#include <thread>
#include <mutex>
#include <condition_variable>
#include <atomic>
#include <functional>
#include <vector>
#include <list>

using Task = std::function<void()>;

class ThreadPool
{
public:
    ThreadPool(int nThreads = 1);
    ~ThreadPool();

    // 提交任务
    bool submitTask(const Task& task);
    bool submitTask(Task&& task);

    // 等待线程执行完毕
    void join();

private:
    void runTasks();

private:
    std::vector<std::thread> m_threads;             // 工作者线程集合
    std::list<Task> m_taskQueue;                    // 任务队列
    std::atomic<bool> m_exit;                       // 是否要退出
    std::mutex m_taskQueueMutex;
    std::condition_variable m_taskQueueNotEmpty;
};

#endif

ThreadPool.cpp:

ThreadPool::ThreadPool(int nThreads) : m_exit(false)
{
    m_threads.reserve(nThreads);

    for (int i = 0; i < nThreads; i++)
    {
        m_threads.emplace_back(std::move(std::thread(&ThreadPool::runTasks, this)));
    }
}

ThreadPool::~ThreadPool()
{
    join();
}

bool ThreadPool::submitTask(const Task& task)
{
    std::lock_guard<std::mutex> qLock(m_taskQueueMutex);

    if (m_taskQueue.size() == m_taskQueue.max_size())
    {
        return false;
    }

    m_taskQueue.push_back(task);
    m_taskQueueNotEmpty.notify_one();
    return true;
}

bool ThreadPool::submitTask(Task&& task)
{
    std::lock_guard<std::mutex> qLock(m_taskQueueMutex);

    if (m_taskQueue.size() == m_taskQueue.max_size())
    {
        return false;
    }

    m_taskQueue.emplace_back(std::move(task));
    m_taskQueueNotEmpty.notify_one();
    return true;
}

void ThreadPool::join()
{
    m_exit.store(true);
    m_taskQueueNotEmpty.notify_all();

    for (auto&& t : m_threads)
    {
        t.join();
    }

    m_threads.clear();
}

void ThreadPool::runTasks()
{
    Task task;

    while (true)
    {
        std::unique_lock<std::mutex> qLock(m_taskQueueMutex);

        while (m_taskQueue.empty() && !m_exit)
        {
            m_taskQueueNotEmpty.wait(qLock);
        }

        if (m_taskQueue.empty())
        {
            return;
        }

        task = m_taskQueue.front();
        m_taskQueue.pop_front();

        qLock.unlock();

        task();
    }
}

主程序:

#include <iostream>
#include <atomic>
#include "ThreadPool.h"

using namespace std::literals;

static std::atomic_uint32_t count = 0;

int main()
{
    ThreadPool pool(2);

    int n = 1000;
    for (int i = 0; i < n; i++)
    {
        pool.submitTask([]()
            {
                std::this_thread::sleep_for(1ns);
                count++;
            });
    }

    pool.join();

    std::cout << "count = " << count << '\n';
}
count = 1000

gzming
7 声望0 粉丝