Java 如何在文件读/写时使用线程?
家庭作业要求我实现一个程序,通过为每个文件启动一个新线程来计算一个或多个文件(文件名在命令行上指定为参数)中的单词数 我的问题是:run()方法不能抛出IOException,因为Runnable接口中的run()方法不会抛出IOException。我把文件和扫描器构造函数调用放在实现Runnable的类的构造函数中,绕过了编译器的警告,但即使它现在编译得很好,我还是觉得有些可疑,好像我在做一些不符合犹太教义的事情。有什么想法吗Java 如何在文件读/写时使用线程?,java,multithreading,ioexception,Java,Multithreading,Ioexception,家庭作业要求我实现一个程序,通过为每个文件启动一个新线程来计算一个或多个文件(文件名在命令行上指定为参数)中的单词数 我的问题是:run()方法不能抛出IOException,因为Runnable接口中的run()方法不会抛出IOException。我把文件和扫描器构造函数调用放在实现Runnable的类的构造函数中,绕过了编译器的警告,但即使它现在编译得很好,我还是觉得有些可疑,好像我在做一些不符合犹太教义的事情。有什么想法吗 import java.io.File; import java.
import java.io.File;
import java.util.Scanner;
import java.io.FileNotFoundException;
import java.io.IOException;
public class WordCounter implements Runnable {
File inFile;
Scanner in;
int characters;
int words;
int lines;
int[] counted;
public WordCounter(String aFile) throws FileNotFoundException {
inFile = new File(aFile);
in = new Scanner(inFile);
counted = new int[3];
}
public int[] getTotals() {
return counted;
}
public void run() {
characters = 0;
words = 0;
lines = 0;
while (in.hasNextLine()) {
String thisLine = in.nextLine();
lines++;
Scanner line = new Scanner(thisLine);
while (line.hasNext()) {
String thisWord = line.next();
words++;
characters++; // because each call to line.next() strips a whitespace character
Scanner word = new Scanner(thisWord);
word.useDelimiter("");
while (word.hasNext()) {
char ch = word.next().charAt(0);
characters++;
}
}
}
counted[0] = characters;
counted[1] = words;
counted[2] = lines;
}
}
在构造函数中初始化成员变量通常是一种好的做法。我认为您做的是正确的,而且,我会将
字符
、单词
、和行
的初始化也移到构造函数中。您可以使异常静音,并中止线程内的文件操作。关闭异常是否是一个好主意取决于您试图做什么
try {
inFile = new File(aFile);
} catch (FileNotFoundException e) {
System.out.println("file not found, aborting operation.");
return;
}
但是,我认为在构造函数中初始化文件没有什么错;如果您希望尽早失败,而不是等到以后再失败,这是一个非常好的做法。如果问题是已检查的异常,那么一个常见的习惯用法是将其转换为RuntimeException,如下所示:
try {
...
} catch (IOException e) {
throw new RuntimeException(e);
}
基本上,你抓,转化和再抓。RuntimeException被取消选中,因此方法签名不需要声明它。我认为一般的经验法则是尽可能靠近抛出异常的位置来处理异常。是什么阻止您的runnable处理异常而不是main()或创建runnable的任何东西
我同意变量初始化通常最好在构造函数中完成,但是当使用runnables时,如果在run()方法中进行构造,您将获得更好的性能。我特别谈论的变量实际上需要一些时间来处理;int[3]不会对构造函数或run方法产生影响,但扫描程序和文件可能取决于它们在初始化时所做的操作(例如,扫描程序是否缓冲文件的第一行?)。在我看来,这是个坏主意。您现在有一个未经检查的异常,编译器不会警告您。这样做有什么意义?异常仍然会被抛出,但现在要到运行时才会被捕获。我曾想过这样做,但在本章之前的章节中,鼓励学生不要在课堂上捕获异常,因为在课堂上,您可能无法像您(或其他程序员)那样有效地处理异常可以在使用类的主方法中处理它们。(希望这是有意义的…)我想我还是有点不确定什么时候该做出判断。说到底,这是一个判断。这只是我的意见。如果您的runnable无法处理扫描程序/文件引发的异常,那么为什么让您的runnable实例化这些类型?为什么不将有效的扫描程序传递到Runnable中呢。这将使您的try/catch位于main()中,听起来似乎就是您要处理此异常的地方。除了例外,你最终做的事情才是最重要的。如果你能从中恢复过来,那就扔掉它。如果您只是想记录日志并默默地失败,我建议您在Runnable中捕获它。