【问题标题】:how to use threads with file reading/writing?如何在文件读/写中使用线程?
【发布时间】:2011-08-09 01:19:59
【问题描述】:

一项家庭作业要求我实现一个程序,该程序通过为每个文件启动一个新线程来计算一个或多个文件中的单词(文件名被指定为命令行上的参数)。

这是我的问题:run() 方法不能抛出 IOException,因为 Runnable 接口中的 run() 方法不会抛出 IOException。通过将 File 和 Scanner 构造函数调用放在实现 Runnable 的类的构造函数中,我已经绕过了编译器的警告,但即使它现在编译得很好,我仍然不知何故感到阴暗,就像我在做一些不洁之事。有什么想法吗?

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;
    }

}

【问题讨论】:

    标签: java multithreading ioexception


    【解决方案1】:

    我认为一般的经验法则是在尽可能接近抛出异常的地方处理异常。是什么阻止你的 runnable 处理异常而不是你的 main() 或任何正在创建 runnables 的东西?

    我同意变量初始化通常最好在构造函数中完成,但是当使用 runnables 时,如果该构造发生在你的 run() 方法中,你将获得更好的性能。我专门谈论实际上需要一些时间来处理的变量; int[3] 无论是在构造函数还是运行方法中都不会产生影响,但是 Scanner 和 File 可能取决于它们在初始化时所做的事情(例如,Scanner 是否缓冲文件的第一行?)。

    【讨论】:

    • 我曾想过这样做,但在这一章之前的一章中,鼓励学生不要在课堂上捕获异常,因为你可能无法处理它们就像您(或其他一些程序员)可以在使用您的类的主要方法中一样有效地处理它们。 (希望这是有道理的......)我想我仍然有点不确定何时做出这些判断。
    • 归根结底,它一个判断电话。这只是我的意见。如果您的可运行程序无法处理扫描仪/文件引发的异常,那么为什么要让您的可运行程序实例化这些类型呢?为什么不将有效的 Scanner 传递给您的 Runnable。这会将您的 try/catch 保留在 main() 中,这听起来像是您要处理此异常的地方。你最终对异常所做的事情才是最重要的。如果你能从中恢复过来,那就扔掉它。如果您只是要记录并静默失败,我会说在 Runnable 中捕获它。
    【解决方案2】:

    在构造函数中初始化成员变量通常是好的做法。我认为你在做正确的事情,此外,我会将characterswordslines 的初始化也移动到构造函数中。

    【讨论】:

      【解决方案3】:

      您可以静默异常,并中止线程内的文件操作。使异常静音是否是一个好主意取决于您尝试执行的操作。

      try {
          inFile = new File(aFile);
      } catch (FileNotFoundException e) {
          System.out.println("file not found, aborting operation.");
          return;
      }
      

      但是,我认为在构造函数中初始化文件并没有错;如果您想早点失败而不是等到以后再失败,这是一个非常好的做法。

      【讨论】:

        【解决方案4】:

        如果问题是已检查异常,那么常见的做法是将其转换为 RuntimeException,如下所示:

        try {
         ...
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        

        基本上你捕捉,转换和重新抛出。 RuntimeException 未选中,因此方法签名不需要声明它。

        【讨论】:

        • 这是一个坏主意 IMO。您现在有一个未经检查的异常,编译器不会警告您。这样做有什么意义?仍然会抛出异常,但现在直到运行时才会被捕获。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-06-09
        • 2019-07-23
        • 1970-01-01
        • 2023-04-01
        • 2018-11-14
        相关资源
        最近更新 更多