この実装を見ると
class Logger {
private final BufferedWriter w;
public Logger(final File file) throws IOException {
this.w = new BufferedWriter(new FileWriter(file));
LoggerRegistry.register(this);
}
public void log(String s) throws IOException {
synchronized (this.w) {
this.w.write(s);
this.w.write("\n");
}
}
public void close() throws IOException {
this.w.close();
}
}
ファイルは開いたままです。
複数のスレッドがある場合は、書き込みメソッドで同期する必要があります (ただし、これはどのような場合でも考慮する必要があります)。
ファイルが開いたままの場合、次の問題が考えられます。
理論的には、ファイル ハンドルが不足する可能性があります。これらは制限される場合があります ( ulimit -a
Linux システムの例を参照)。各ロガーは 1 つのハンドルを消費します。
バッファリングなしでを使用するFileWriter
と、 の呼び出しごとに I/O 呼び出しが発生しますwrite
。これはかなり遅くなる可能性があります。
BufferedWriter
の上にを使用する場合FileWriter
は、プログラムの最後で適切に閉じられるようにする必要があります。そうしないと、バッファー内の残りのコンテンツがディスクに書き込まれない可能性があります。したがって、すべてのロガーを正しく閉じる必要があるプログラムの周りに try/finally ブロックが必要です。
したがって、すべてのロガーを登録する必要があります。これは簡略化されたバージョンです (スレッドセーフではありません)。
class LoggerRegistry {
private final static List<Logger> loggers = new ArrayList<Logger>();
public static void register(Logger l) {
loggers.add(l);
}
public static void close() {
for (Logger l : loggers) {
try {
l.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
これをメインプログラムで次のように使用します。
public static void main(String[] args) throws IOException {
try {
final Logger l = new Logger(new File("/tmp/1"));
l.log("Hello");
// ...
} finally {
LoggerRegistry.close();
}
}
Web アプリケーションがある場合は、close
メソッドをServletContextListener
(method contextDestroyed
) で呼び出すことができます。
最大のパフォーマンスの向上は、おそらくBufferedWriter
. close
を呼び出す必要があるため、書き込み操作ごとに開いたり閉じたりすると、この利点が失われますflush
。したがって、開いているファイルとバッファリングを組み合わせると、非常に高速になります。