[英]Thread Pool C++
我有以下for循环:
for (int i = 0; i < 100; i++) {
someJob();
}
我想只用5个线程运行这个函数,我该怎么办?
我尝试的是使用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;
}
}
有什么建议吗? (我不能用boost)
谢谢!
你可以简单地使用std::async
。
如果要在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();
}
可以修改相同的代码以使用naked std::thread
。
您可以创建一个函数来测试您的线程数组,以找到一个空的线程来运行每个连续的作业。 像这样的东西:
// 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();
}
这是在运行中实现线程池的一种方法,同时保持安全。
#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将允许您轻松地执行此操作,同时隐藏整个线程池。 大多数编译器都有内置支持,但请参阅手册以了解具体选项。 (gcc只需要传递-fopenmp
作为选项)。
#pragma omp parallel for num_threads(5)
for (int i = 0; i < 100; i++) {
someJob(i);
}
然后将你的工作分成5个线程。 如果省略num_threads(5)
,它将选择多个线程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.