我很开心,让自己保持警惕。
我需要在文件中组织多线程查找:
用户输入find(路径)和find(word);
.txt
个文件并将结果添加到队列中; 问题:
MultiThreadingSearch
(或更好地使用合成)?代码:
import java.util.*;
import java.io.*;
class ArrayListOfFiles {
private Node first, last;
private class Node {
String item;
Node next;
}
public boolean isEmpty() {
return first == null;
}
public synchronized void enqueue(String item) {
Node oldlast = last;
last = new Node();
last.item = item;
last.next = null;
if (isEmpty())
first = last;
else
oldlast.next = last;
}
public synchronized String dequeue() {
String item = first.item;
first = first.next;
if (isEmpty())
last = null;
return item;
}
}
class FolderScan extends MultiThreadingSearch implements Runnable {
FolderScan(String path, String whatFind) {
super(path, whatFind);
}
@Override
public void run() {
findFiles(path);
}
ArrayListOfFiles findFiles(String path) {
File root = new File(path);
File[] list = root.listFiles();
for (File titleName : list) {
if (titleName.isDirectory()) {
findFiles(titleName.getAbsolutePath());
} else {
if (titleName.getName().toLowerCase().endsWith((".txt"))) {
textFiles.enqueue(titleName.getName());
}
}
}
return textFiles;
}
}
class FileScan extends MultiThreadingSearch implements Runnable {
Scanner scanner = new Scanner((Readable) textFiles);
Set<String> words = new HashSet<String>();
int matches = 0;
FileScan(String file, String whatFind) {
super(file, whatFind);
Thread wordFind = new Thread();
wordFind.start();
}
@Override
public void run() {
while (scanner.hasNext()) {
String word = scanner.next();
words.add(word);
}
if (words.contains(this.whatFind)) {
System.out.println("File:" + this.path);
matches++;
}
System.out.println(matches);
}
}
public class MultiThreadingSearch {
String path;
String whatFind;
ArrayListOfFiles textFiles;
MultiThreadingSearch(String path, String whatFind) {
this.path = path;
this.whatFind = whatFind;
this.textFiles = new ArrayListOfFiles();
Thread pathFind = new Thread(new FolderScan(path, whatFind));
// pathFind.start();
if (!textFiles.isEmpty()) {
@SuppressWarnings("unused")
FileScan fileScan = new FileScan(textFiles.dequeue(), whatFind);
}
}
// ask user about input
public static void askUserPathAndWord() {
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(System.in));
String path;
String whatFind;
try {
System.out.println("Please, enter a Path and Word"
+ "(which you want to find):");
System.out.println("Please enter a Path:");
path = bufferedReader.readLine();
System.out.println("Please enter a Word:");
whatFind = bufferedReader.readLine();
if (path != null && whatFind != null) {
new MultiThreadingSearch(path, whatFind);
System.out.println("Thank you!");
} else {
System.out.println("You did not enter anything");
}
} catch (IOException | RuntimeException e) {
System.out.println("Wrong input!");
e.printStackTrace();
}
}
public static void main(String[] args) {
askUserPathAndWord();
}
}
我从这段代码中得到Exception in thread "main" java.lang.StackOverflowError
怎么能解决这个任务?
谢谢,
纳扎尔。
答案 0 :(得分:5)
检查BlockingQueue它完全符合您的需要。线程可以阻塞,直到某个其他线程将新项添加到队列中 至于如何分解你的系统。我会做以下事情:
Runnable
。您将path
和queue
传递给它。它会搜索txt文件的路径并将它们添加到队列中。Runnable
。您将whatFind
和queue
传递给它,它从队列中获取新文件并检查其内容。类似的东西:
BlockingQueue<File> queue = new LinkedBlockingQueue<File>();
String path = ...;
String whatFind = ...;
FolderScan folderScan = new FolderScan(path, queue);
FileScan fileScan = new FileScan(whatFind, queue);
Executor executor = Executors.newCachecThreadPool();
executor.execute(folderScan);
executor.execute(fileScan);
如果您希望FileScan
等到FolderScan
向队列中添加内容,您可以使用take方法:
BlockingQueue<File> queue;
File toProcess = queue.take(); // this line blocks current thread (FileScan) until someone adds new item to the queue.
答案 1 :(得分:0)
更改后:
package task;
import java.util.concurrent.*;
import java.util.*;
import java.io.*;
class FolderScan implements Runnable {
private String path;
private BlockingQueue<File> queue;
private CountDownLatch latch;
private File endOfWorkFile;
FolderScan(String path, BlockingQueue<File> queue, CountDownLatch latch,
File endOfWorkFile) {
this.path = path;
this.queue = queue;
this.latch = latch;
this.endOfWorkFile = endOfWorkFile;
}
public FolderScan() { }
@Override
public void run() {
findFiles(path);
queue.add(endOfWorkFile);
latch.countDown();
}
private void findFiles(String path) {
try {
File root = new File(path);
File[] list = root.listFiles();
for (File currentFile : list) {
if (currentFile.isDirectory()) {
findFiles(currentFile.getAbsolutePath());
} else {
if (currentFile.getName().toLowerCase().endsWith((".txt"))) {
queue.put(currentFile);
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class FileScan implements Runnable {
private String whatFind;
private BlockingQueue<File> queue;
private CountDownLatch latch;
private File endOfWorkFile;
public FileScan(String whatFind, BlockingQueue<File> queue,
CountDownLatch latch, File endOfWorkFile) {
this.whatFind = whatFind;
this.queue = queue;
this.latch = latch;
this.endOfWorkFile = endOfWorkFile;
}
public FileScan() { }
Set<String> words = new HashSet<String>();
int matches = 0;
@Override
public void run() {
while (true) {
try {
File file;
file = queue.take();
if (file == endOfWorkFile) {
break;
}
scan(file);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
latch.countDown();
}
private void scan(File file) {
Scanner scanner = null;
try {
scanner = new Scanner(file);
} catch (FileNotFoundException e) {
System.out.println("FileNotFoundException.");
e.printStackTrace();
}
while (scanner.hasNext()) {
String word = scanner.next();
words.add(word);
}
if (words.contains(this.whatFind)) {
matches++;
}
String myStr = String.format("File: %s and the number of matches "
+ "is = %d", file.getAbsolutePath(), matches);
System.out.println(myStr);
matches = 0;
}
// ask user about input
public void askUserPathAndWord() {
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(System.in));
String path;
String whatFind;
BlockingQueue<File> queue = new LinkedBlockingQueue<File>();
try {
System.out.println("Please, enter a Path and Word"
+ "(which you want to find):");
System.out.println("Please enter a Path:");
path = bufferedReader.readLine();
System.out.println("Please enter a Word:");
whatFind = bufferedReader.readLine();
if (path != null && whatFind != null) {
File endOfWorkFile = new File("GameOver.tmp");
CountDownLatch latch = new CountDownLatch(2);
FolderScan folderScan = new FolderScan(path, queue, latch,
endOfWorkFile);
FileScan fileScan = new FileScan(whatFind, queue, latch,
endOfWorkFile);
Executor executor = Executors.newCachedThreadPool();
executor.execute(folderScan);
executor.execute(fileScan);
latch.await();
System.out.println("Thank you!");
} else {
System.out.println("You did not enter anything");
}
} catch (IOException | RuntimeException e) {
System.out.println("Wrong input!");
e.printStackTrace();
} catch (InterruptedException e) {
System.out.println("Interrupted.");
e.printStackTrace();
}
}
/**
* @param args
*/
public static void main(String[] args) {
new FileScan().askUserPathAndWord();
}
}
答案 2 :(得分:-1)
这可能听起来不太具有建设性,但您可以先修复该代码或先阅读this之类的内容,然后再丢弃代码。 Stackoverflow通常来自比预期更深的递归。确保递归方法中存在一些阻止递归的条件。