我有一个包含100个.txt
个文件的文件夹,每个文件有20个或+ MB。
所有文件都有大约2*10^5 lines of UTF-8 encoded text
。
什么是,可能使用多线程,找到哪些文件包含固定密钥字符串的最快方法? (包含的标准与java .contains()函数相同,即普通子字符串。
我在SO上找到了几种方法,但没有使用multithreading
(为什么?),所有这些方法似乎根据要求改变速度,我似乎无法了解哪种方法对我更好。
例如这种超级复杂的方法:
似乎比使用BufferedReader
和.contains()
函数的简单逐行搜索慢2倍。怎么会这样?
我怎样才能充分利用多线程?该程序在功能非常强大的多核计算机上运行。
我正在寻找的输出是哪些文件包含字符串,可能,在哪一行。
答案 0 :(得分:1)
我会让其他问题的答案不言自明,但多线程不太可能对存储在单个磁盘上的数据的I / O绑定任务有所帮助。假设您的文件夹存储在单个磁盘上,磁盘缓存最优化的用例是单线程访问,因此这可能是最有效的解决方案。原因是因为从磁盘读取数据可能比在数据加载到内存后查看数据要慢,因此磁盘读取速率是限制的。
使用BufferedReader和contains()函数的简单解决方案可能是最快的,因为这可能是高度优化的库代码。
现在,如果您的数据被分片到多个磁盘上,那么运行多个线程可能是值得的,这取决于操作系统执行磁盘缓存的方式。如果您要对不同的字符串进行多次搜索,而不是在第一次搜索时都知道,以便单次传递方法不起作用,则可能值得将所有文件加载到内存中,然后仅执行多线程搜索记忆中。但是,你的问题不再是一个文件搜索问题,而是更常见的数据搜索问题。
答案 1 :(得分:0)
以下代码完成了工作。
它将进入您的目录并查找所有文件。 然后将为每个文件创建一个新线程并查找目标字符串。
请确保根据需要更改TheThread类中文件夹和目标String的路径
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
//class used for thread
class TheThread implements Runnable {
int counter = 0;
//to get stream of paths
Stream<Path> streamOfFiles = Files.walk(Paths.get("./src/Multi_tasking/Files"));
//List of total all files in the folder
List<Path> listOfFiles = streamOfFiles.collect(Collectors.toList());
//because Files.walk may throw IOException
public TheThread() throws IOException {
}
@Override
public void run() {
//increments counter to access the indexes of the list
counter++;
//Calling the method for search file at index counter and target String
SearchTextInMultipleFilesUsingMultiThreading.lookIn(listOfFiles.get(counter), "target String");
}
}
public class SearchTextInMultipleFilesUsingMultiThreading {
//method responsible for searching the target String in file
public static void lookIn(Path path, String text) {
try {
List<String> texts = Files.readAllLines(path);
boolean flag = false;
for (int i = 0; i < texts.size(); i++) {
String str = texts.get(i);
if (str.contains(text)) {
System.out.println("Found \"" + text + "\" in " + path.getFileName() + " at line : " + (i + 1) + " from thread : " + Thread.currentThread().getName());
flag = true;
}
}
if (!flag) {
System.out.println("\"" + text + "\" not found in " + path.getFileName() + " through thread : " + Thread.currentThread().getName());
}
} catch (IOException e) {
System.out.println("Error while reading " + path.getFileName());
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
//creating object of our thread class
TheThread theThread = new TheThread();
//getting the number of files in the folder
int numberOfFiles = theThread.listOfFiles.size() - 1;
//if the folder doesn't contain any file at all
if (numberOfFiles == 0) {
System.out.println("No file found in the folder");
System.exit(0);
}
//creating the List to store threads
List<Thread> listOfThreads = new ArrayList<>();
//keeping required number of threads inside the list
for (int i = 0; i < numberOfFiles; i++) {
listOfThreads.add(new Thread(theThread));
}
//starting all the threads
for (Thread thread :
listOfThreads) {
thread.start();
}
}
}