线程的开辟数量如何在运行时决定,看如下例子
#include <iostream>
#include <thread>
#include <vector>
#include <algorithm>
#include <numeric>
#include <functional>
template<typename _Iterator, typename T>
class Accum
{
public:
int operator()(_Iterator begin, _Iterator end, T& temp_sum)
{
temp_sum = std::accumulate(begin, end, temp_sum);
return temp_sum;
}
};
//多线程求和函数
template<typename _Iterator, typename _T> //Iterator:迭代器 T 是数据类型
_T Sum(_Iterator first, _Iterator last, _T& sum)
{
//获取容器内元素个数
unsigned int len = std::distance(first, last); //返回两个迭代器之间的距离
std::cout << "容器内元素个数为:" << len << std::endl;
//获取当前机器支持的并发线程数
unsigned int hardware_thread = std::thread::hardware_concurrency(); //获取当前机器支持的并发线程数
std::cout << "当前机器支持的并发线程数为:" << hardware_thread << std::endl;
//每个线程最小处理元素个数
unsigned int min_deal_thread = 23;
//当前最大需要开辟线程的数目
unsigned int max_thread = (len - 1 + min_deal_thread) / min_deal_thread;
std::cout << "当前最大需要开辟的线程数为:" << max_thread << std::endl;
//当前实际需要开辟的线程数(如果机器支持的并发数返回为0,则开辟2个线程,否则取前机器支持的并发线程数和当最大需要开辟线程的数目的较小值)
unsigned int effect_thread_num = hardware_thread == 0 ? 2 : std::min(max_thread, hardware_thread);
std::cout << "当前实际需要开辟的线程数为:" << effect_thread_num << std::endl;
int bolck = len / effect_thread_num;
std::vector<std::thread> threads(effect_thread_num);
std::vector<_T> temp_sum(effect_thread_num);
_Iterator begin = first;
Accum<_Iterator, _T> accum;
for (int i = 0; i < (effect_thread_num - 1); ++i) //最后一块单独算是因为不确定最后一块是否刚好够block那么大
{
_Iterator end = begin;
std::advance(end, bolck);
threads[i] = std::thread(accum, begin, end, std::ref(temp_sum[i]));
begin = end;
}
threads[effect_thread_num - 1] = std::thread(accum, begin, last, std::ref(temp_sum[effect_thread_num - 1]));
std::for_each(threads.begin(), threads.end(), std::mem_fn(&std::thread::join));
sum = std::accumulate(temp_sum.begin(), temp_sum.end(), sum);
std::cout << "所有元素和为:" << sum << std::endl;
return sum;
}
int main()
{
std::vector<int> vec;
int sum = 0;
for (int i = 0; i < 10; ++i)
{
vec.push_back(i + 1);
}
Sum(vec.begin(), vec.end(), sum);
return 0;
}
运行结果:
代码逻辑如下:
①获取容器元素个数
②获取当前机器支持并发线程的数量
③设定每个线程的最小执行数量,然后进一步确定运行时线程的数量(详情见代码和注释)
④批量运行,并批量join
人,总是要有一点精神的,不是吗