我试图教我使用执行服务使用多线程技术,我想知道什么是最好的做法是执行我的代码如下 - 我读的文本文件的目录和检查字/词 -
此外,我很困惑是否正在使用多个线程,如果我要做的就是为每个通过的文件列表。多个文件正在对曾在一次?
大类
public class Application {
private long totalCharacterCount;
private long totalLineCount;
private final File[] fileList;
private final static String _DIRECTORY = "src//documents";
public Application(String directory){
fileList = new File(directory).listFiles();
}
public synchronized File[] getFileList(){
return fileList;
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executor = Executors.newFixedThreadPool(4);
Application x = new Application(_DIRECTORY);
for(File file : x.getFileList()){
Future<FileReadings> response = executor.submit(new Process(file));
x.totalCharacterCount += response.get().characterCount;
x.totalLineCount += response.get().lineCount;
}
System.out.println("Total lines in all documents: " + x.totalLineCount);
System.out.println("Total characters in all documents: " + x.totalCharacterCount);
executor.shutdown();
}
}
流程类
public class Process implements Callable<FileReadings> {
private FileReadings object;
private File file;
public Process(File file){
FileReadings obj = new FileReadings();
this.object = obj;
this.file = file;
}
public void CountCharacters(File file){
int count = 0;
try {
BufferedReader reader = Files.newBufferedReader(file.toPath());
while(reader.read() != -1){
count++;
}
object.characterCount = reader.read();
} catch (IOException ex) {
ex.printStackTrace();
}
object.characterCount = count;
}
public void CountLines(File file){
try {
Stream<String> text = Files.lines(file.toPath());
object.lineCount = text.count();
} catch (IOException ex) {
ex.printStackTrace();
}
}
public FileReadings call() throws Exception {
CountCharacters(this.file);
CountLines(this.file);
System.out.println("THERE WERE: " + object.characterCount + " CHARACTERS IN: " + file.getName());
System.out.println("THERE WERE: " + object.lineCount + " LINES IN: " + file.getName());
return object;
}
}
文件进行读取类
public class FileReadings {
long characterCount;
long lineCount;
}
结果是:
THERE WERE: 65 CHARACTERS IN: test1.txt
THERE WERE: 10 LINES IN: test1.txt
THERE WERE: 88 CHARACTERS IN: test2.txt
THERE WERE: 21 LINES IN: test2.txt
Total lines in all documents: 31
Total characters in all documents: 153
没有。这不是正确的方法。你提交一个过程,然后通过调用get()
未来,您阻止并等待它完成,如此有效它是一个同步处理。有两种方法可以做到并行,异步处理:
1)invokeAll()
这是更简单的方法,但它需要您提前创建所有的流程实例,所以这取决于你想要多少并行任务执行(如果你有百万人,你会打一个内存限制)。一旦你创建的过程中,您提交他们在一次执行程序。它会并行执行所有任务(根据线程池的大小),当所有完成后返回。
List<Callable<FileReadings>> tasks = new Arraylist<>();
for (File file : x.getFileList()) {
tasks.add(new Process(file));
}
// submit all processes at once. they will be processed in parallel
// this call blocks until all tasks are finished
List<Future<FileReadings>> responses = executor.invokeAll(tasks);
// at this point all processes finished. all get() will return immediately
for (Future<FileReadings> response : responses) {
x.totalCharacterCount += response.get().characterCount;
x.totalLineCount += response.get().lineCount;
}
2)submit()
当你创建一个进程,并立即提交,因此内存的要求不变(不包括执行人)这种解决方案更具可扩展性。不过,你需要自己管理的对策:
List<Future<FileReadings>> responses = new ArrayList<>();
for (File file : x.getFileList()) {
responses.add(executor.submit(new Process(file)));
}
// at this point all processes submitted but not finished.
// need to check which is finished at intervarls
while (responses.isEmpty() == false) {
Thread.sleep(1000); // allow some processing time for tasks
// ListIterator allows removing items
ListIterator<Future<FileReadings>> itr = responses.listIterator();
while (itr.hasNext()) {
Future<FileReadings> response = itr.next();
// if task is complete, get it and remove from list
if (response.isDone()) {
x.totalCharacterCount += response.get().characterCount;
x.totalLineCount += response.get().lineCount;
itr.remove();
}
}
}