版权声明:本文为博主原创文章,可以转载但必须注明出处。 https://blog.csdn.net/nirendao/article/details/88096195
曾经写了一篇博客做一些大数据的处理,但是其中在读取一个大文件的时候,并没有采取并行处理的方式。那么,一个大文件,为了能够批量处理,现在由多个线程来同时读它,各自读取一块(所读内容互不相同)。这么做会有问题吗?
答:如果只有读线程,那么没有问题。因为,不同的线程可以创建自己的文件描述符表项,再分别指向不同的文件表项,而每个文件表项里面可以有不同的当前文件偏移量,所以没有问题。而且这种情况也根本不需要用到锁。
以下是一个实际的例子。
首先,假设当前目录有一个文件1.txt(注意:必须是UNIX格式而非DOS格式),其内容如下:
111111111
222222222
333333333
444444444
555555555
666666666
777777777
888888888
999999999
000000000
处理代码如下:
#include <thread>
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <chrono>
using namespace std;
void thread_read_file(int tid, const string& file_path)
{
ifstream file(file_path.c_str(), ios::in);
if (!file.good()) {
stringstream ss;
ss << "Thread " << tid << " failed to open file: " << file_path << "\n";
cout << ss.str();
return;
}
int pos;
if (tid == 0) pos = 0;
else pos = tid*10;
file.seekg(pos, ios::beg);
string line;
getline(file, line);
stringstream ss;
ss << "Thread " << tid << ", pos=" << pos << ": " << line << "\n";
cout << ss.str();
}
void test_detach(const string& file_path)
{
for (int i=0; i<10; ++i) {
std::thread th(thread_read_file, i, file_path);
th.detach();
}
}
void test_join(const string& file_path)
{
vector<std::thread> vec_threads;
for (int i=0; i<10; ++i) {
std::thread th(thread_read_file, i, file_path);
vec_threads.emplace_back(std::move(th)); // push_back() is also OK
}
auto it = vec_threads.begin();
for (; it != vec_threads.end(); ++it) {
(*it).join();
}
}
int main()
{
string file_path = "./1.txt";
test_detach(file_path);
std::this_thread::sleep_for(std::chrono::seconds(1)); // wait for detached threads done
test_join(file_path);
return 0;
}
以上代码中,展示了线程的detach和join的2种写法。对于本例来说,实际程序中,还是应该写成join. 道理也很简单。如果写成了detach,一旦主线程先结束了,那么还没来得及打印的detach的子线程也就再也不会打印其信息了。
(完)