Если вы посмотрите на эту реализацию
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): каждый регистратор потребляет один дескриптор.
Если вы используете FileWriter
без буферизации, у вас есть вызовы ввода/вывода для каждого вызова 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();
}
}
Если у вас есть веб-приложение, вы могли бы назвать close
метод в ServletContextListener
(метод contextDestroyed
).
Наибольшее усиление производительности, вероятно, является BufferedWriter
. Это преимущество теряется, если вы открываете/закрываете его для каждой операции записи, так как close
должен позвонить flush
. Таким образом, комбинация открытого файла вместе с буферизацией будет довольно быстрой.
BTW в вашем примере, если 'write' генерирует исключение, автор не закрывается сразу после' write'. – Beryllium