如何在 java 中应用多线程在目录(主目录和给定的单词)中查找单词并递归地查找其子目录
How to apply multithreading in java to find a word in a directory(main directory and the word given) and recursively its subdirectories
我是 Stack Overflow 的新手,也是 Java 的初学者,所以如果我以不正确的方式提出这个问题,请原谅我。
问题
我有一个作业告诉我使用多线程来搜索给定单词的文件,它可能存在于任何文件中在给定目录(基本上是整个目录)的任何级别上键入 .txt 和 .html。如果文件包含给定的单词,则必须在控制台上显示文件的绝对文件路径。
我尝试了什么
所以我想到把这个任务分成2个部分,分别是Searching和Multithreading,
我能够获得搜索部分( File_search.java )。通过搜索目录并找到给定单词的所有文件,该文件给出了令人满意的结果。
File_search.java
public class File_search{
String fin_output = "";
public String searchInTextFiles(File dir,String search_word) {
File[] a = dir.listFiles();
for(File f : a){
if(f.isDirectory()) {
searchInTextFiles(f,search_word);
}
else if(f.getName().endsWith(".txt") || f.getName().endsWith(".html") || f.getName().endsWith(".htm") ) {
try {
searchInFile(f,search_word);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
return fin_output;
}
public void searchInFile(File f,String search_word) throws FileNotFoundException {
final Scanner sc = new Scanner(f);
while(sc.hasNextLine()) {
final String lineFromFile = sc.nextLine();
if(lineFromFile.contains(search_word)) {
fin_output += "FILE : "+f.getAbsolutePath().toString()+"\n";
}
}
}
现在,我希望能够使用 ThreadPoolExecuter 服务使用多个线程来执行任务 File_search.java。我不确定我是否可以使用 Runnable 、 Callable 或使用 Thread class 或任何其他方法来做到这一点?
你能帮我处理多线程部分的代码吗?谢谢:)
我同意@chrylis -cautiouslyoptimistic 的评论,但出于理解目的,下文会对您有所帮助。
一种更简单的方法是在主线程中遍历目录,我的意思是您在函数 searchInTextFiles
中添加的逻辑,并像在函数 [=12= 中那样执行搜索逻辑] 在一个大小为 10 的线程池中。
下面的示例代码将帮助您更好地理解它。
public class Traverser {
private List<Future<String>> futureList = new ArrayList<Future<String>>();
private ExecutorService executorService;
public Traverser() {
executorService = Executors.newFixedThreadPool(10);
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("Started");
long start = System.currentTimeMillis();
Traverser traverser = new Traverser();
traverser.searchInTextFiles(new File("Some Directory Path"), "Some Text");
for (Future<String> future : traverser.futureList) {
System.out.println(future.get());
}
traverser.executorService.shutdown();
while(!traverser.executorService.isTerminated()) {
System.out.println("Not terminated yet, sleeping");
Thread.sleep(1000);
}
long end = System.currentTimeMillis();
System.out.println("Time taken :" + (end - start));
}
public void searchInTextFiles(File dir,String searchWord) {
File[] filesList = dir.listFiles();
for(File file : filesList){
if(file.isDirectory()) {
searchInTextFiles(file,searchWord);
}
else if(file.getName().endsWith(".txt") || file.getName().endsWith(".html") || file.getName().endsWith(".htm") ) {
try {
futureList.add(executorService.submit(new SearcherTask(file,searchWord)));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}}
public class SearcherTask implements Callable<String> {
private File inputFile;
private String searchWord;
public SearcherTask(File inputFile, String searchWord) {
this.inputFile = inputFile;
this.searchWord = searchWord;
}
@Override
public String call() throws Exception {
StringBuilder result = new StringBuilder();
Scanner sc = null;
try {
sc = new Scanner(inputFile);
while (sc.hasNextLine()) {
final String lineFromFile = sc.nextLine();
if (lineFromFile.contains(searchWord)) {
result.append("FILE : " + inputFile.getAbsolutePath().toString() + "\n");
}
}
} catch (Exception e) {
//log error
throw e;
} finally {
sc.close();
}
return result.toString();
}}
我是 Stack Overflow 的新手,也是 Java 的初学者,所以如果我以不正确的方式提出这个问题,请原谅我。
问题
我有一个作业告诉我使用多线程来搜索给定单词的文件,它可能存在于任何文件中在给定目录(基本上是整个目录)的任何级别上键入 .txt 和 .html。如果文件包含给定的单词,则必须在控制台上显示文件的绝对文件路径。
我尝试了什么
所以我想到把这个任务分成2个部分,分别是Searching和Multithreading, 我能够获得搜索部分( File_search.java )。通过搜索目录并找到给定单词的所有文件,该文件给出了令人满意的结果。
File_search.java
public class File_search{
String fin_output = "";
public String searchInTextFiles(File dir,String search_word) {
File[] a = dir.listFiles();
for(File f : a){
if(f.isDirectory()) {
searchInTextFiles(f,search_word);
}
else if(f.getName().endsWith(".txt") || f.getName().endsWith(".html") || f.getName().endsWith(".htm") ) {
try {
searchInFile(f,search_word);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
return fin_output;
}
public void searchInFile(File f,String search_word) throws FileNotFoundException {
final Scanner sc = new Scanner(f);
while(sc.hasNextLine()) {
final String lineFromFile = sc.nextLine();
if(lineFromFile.contains(search_word)) {
fin_output += "FILE : "+f.getAbsolutePath().toString()+"\n";
}
}
}
现在,我希望能够使用 ThreadPoolExecuter 服务使用多个线程来执行任务 File_search.java。我不确定我是否可以使用 Runnable 、 Callable 或使用 Thread class 或任何其他方法来做到这一点? 你能帮我处理多线程部分的代码吗?谢谢:)
我同意@chrylis -cautiouslyoptimistic 的评论,但出于理解目的,下文会对您有所帮助。
一种更简单的方法是在主线程中遍历目录,我的意思是您在函数 searchInTextFiles
中添加的逻辑,并像在函数 [=12= 中那样执行搜索逻辑] 在一个大小为 10 的线程池中。
下面的示例代码将帮助您更好地理解它。
public class Traverser {
private List<Future<String>> futureList = new ArrayList<Future<String>>();
private ExecutorService executorService;
public Traverser() {
executorService = Executors.newFixedThreadPool(10);
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("Started");
long start = System.currentTimeMillis();
Traverser traverser = new Traverser();
traverser.searchInTextFiles(new File("Some Directory Path"), "Some Text");
for (Future<String> future : traverser.futureList) {
System.out.println(future.get());
}
traverser.executorService.shutdown();
while(!traverser.executorService.isTerminated()) {
System.out.println("Not terminated yet, sleeping");
Thread.sleep(1000);
}
long end = System.currentTimeMillis();
System.out.println("Time taken :" + (end - start));
}
public void searchInTextFiles(File dir,String searchWord) {
File[] filesList = dir.listFiles();
for(File file : filesList){
if(file.isDirectory()) {
searchInTextFiles(file,searchWord);
}
else if(file.getName().endsWith(".txt") || file.getName().endsWith(".html") || file.getName().endsWith(".htm") ) {
try {
futureList.add(executorService.submit(new SearcherTask(file,searchWord)));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}}
public class SearcherTask implements Callable<String> {
private File inputFile;
private String searchWord;
public SearcherTask(File inputFile, String searchWord) {
this.inputFile = inputFile;
this.searchWord = searchWord;
}
@Override
public String call() throws Exception {
StringBuilder result = new StringBuilder();
Scanner sc = null;
try {
sc = new Scanner(inputFile);
while (sc.hasNextLine()) {
final String lineFromFile = sc.nextLine();
if (lineFromFile.contains(searchWord)) {
result.append("FILE : " + inputFile.getAbsolutePath().toString() + "\n");
}
}
} catch (Exception e) {
//log error
throw e;
} finally {
sc.close();
}
return result.toString();
}}