简体   繁体   English

线程池C ++

[英]Thread Pool C++

I have the following for loop: 我有以下for循环:

for (int i = 0; i < 100; i++) {
    someJob();
}

I want to run this function only with 5 threads, how can I do it? 我想只用5个线程运行这个函数,我该怎么办?

What I'm tried is to make array with 5 threads and if the index is equal to 5 to wait all threads and to it again, but I'm sure there is another way to do that: 我尝试的是使用5个线程创建数组,如果索引等于5以等待所有线程再次使用它,但我确信还有另一种方法可以做到这一点:

std::thread t[THREAD_COUNT];
int j=0;

 for (int i = 0; i < 100; i++) {
    t[j++] = std::thread(someJob);
    if (j == THREAD_COUNT)
    {
        for (int k = 0; k < THREAD_COUNT; k++)
        {
            if (t[k].joinable())
                t[k].join();
        }
        j = 0;
    }
}

Any suggestion? 有什么建议吗? (I can't use boost) (我不能用boost)

Thanks! 谢谢!

You can simply use std::async for that. 你可以简单地使用std::async

If you want to execute this function 100 times in 5 different asynchronous actions , then each asynchronous function will execute the function 20 times: 如果要在5个不同的异步操作中执行此函数100次,则每个异步函数将执行该函数20次:

std::vector<std::future> results;
results.reserve(5);
for (auto i = 0; i< 5 ;i++){
   results.emplace_back([]{
     for(auto j = 0; j < 20 ; j++){
       doSomeFunction();
     } 
   });
}

for (auto& f : results){
    f.get();
}

the same code can be modified to use naked std::thread . 可以修改相同的代码以使用naked std::thread

You could make a function that tests your thread array to find a vacant thread to run each successive job on. 您可以创建一个函数来测试您的线程数组,以找到一个空的线程来运行每个连续的作业。 Something like this: 像这样的东西:

// synchronized output to prevent interleaving of results
#define sync_out(m) do{std::ostringstream o; o << m << '\n'; std::cout << o.str();}while(0)

void someJob(int id)
{
    sync_out("thread: " << id);
}

template<typename Job>
void start_thread(std::vector<std::thread>& threads, Job&& job)
{
    // find an ended thread
    for(auto&& thread: threads)
    {
        if(thread.joinable()) // still running or waiting to join
            continue;

        thread = std::thread(job);
        return;
    }

    // if not wait for one
    for(auto&& thread: threads)
    {
        if(!thread.joinable()) // dead thread (not run or already joined)
            continue;

        thread.join();
        thread = std::thread(job);
        return;
    }
}

int main()
{

    std::vector<std::thread> threads(5); // 5 threads

    for(int i = 0; i < 100; i++)
        start_thread(threads, [=]{someJob(i);});

    // wait for any unfinished threads    
    for(auto&& thread: threads)
        if(thread.joinable())
            thread.join();
}

You should use a Thread Pool . 您应该使用线程池

Specifically, you might use the C++ Thread Pool Library CPTL , with which your code would look like this: 具体来说,您可以使用C ++线程池库CPTL ,您的代码将如下所示:

ctpl::thread_pool p(2 /* two threads in the pool */);

for (int i = 0; i < 100; i++) {
    p.push(someJob, "additional_param");
}

Here's one way to implement a thread pool on the fly, while staying safe. 这是在运行中实现线程池的一种方法,同时保持安全。

#include <thread>
#include <vector>
#include <algorithm>
#include <mutex>

void someJob() { /* some lengthy process */ }

int main()
{
    const size_t THREAD_COUNT = 5;
    std::vector<std::thread> threadPool;
    std::mutex mtx;               // to block access to the pool

    for (int i = 0; i < 100; i++) 
    {
        {
            // add new thread to the pool.
            std::lock_guard<std::mutex> lock(mtx);
            threadPool.emplace_back(std::thread([&mtx, &threadPool]()
            {
                someJob();

                // task is done, remove thread from pool
                std::lock_guard<std::mutex> lock(mtx);
                threadPool.erase(
                    std::find_if(threadPool.begin(), threadPool.end(), 
                    [](std::thread& x) 
                    { 
                        if (x.get_id() == std::this_thread::get_id())
                        {
                            x.detach();  // have to call detach, since we can't 
                            return true; // destroy an attached thread.
                        }
                        return false; 
                    })
                );
            }));
        }

        for (;;)
        {
            // wait for a slot to be freed.
            std::this_thread::yield();
            std::lock_guard<std::mutex> lock(mtx);
            if (threadPool.size() < THREAD_COUNT)
            {
                break;
            }
        }
    }

    // wait for the last tasks to be done
    for (;;)
    {
        std::this_thread::yield();
        std::lock_guard<std::mutex> lock(mtx); // works fine without.. but...
        if (threadPool.empty())                // <-- can't call join here, since detached 
        {                                      // threads are not joinable()
            break;
        }
    }
    return 0;
}

OpenMP will allow you to do this trivially, while hiding the entire threadpool. OpenMP将允许您轻松地执行此操作,同时隐藏整个线程池。 Most compilers have build in support, but consult your manual for the specific options. 大多数编译器都有内置支持,但请参阅手册以了解具体选项。 (gcc simply requires passing -fopenmp as an option). (gcc只需要传递-fopenmp作为选项)。

#pragma omp parallel for num_threads(5)
for (int i = 0; i < 100; i++) {
    someJob(i);
}

will then split your work over 5 threads. 然后将你的工作分成5个线程。 If you leave out num_threads(5) it will choose a number of threads itselve. 如果省略num_threads(5) ,它将选择多个线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM