如果你看一下这个实现
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();
}
}
该文件保持打开状态。
如果有多个线程,则必须在 write 方法中进行同步(但无论如何都必须考虑这一点)。
如果文件保持打开状态,则可能存在以下问题:
从理论上讲,您可能会用完文件句柄。这些可能是有限的(ulimit -a
例如,参见 Linux 系统):每个记录器使用一个句柄。
如果使用FileWriter
不带缓冲的 a,则每次调用write
. 这可能会很慢。
如果在 aBufferedWriter
上使用 a 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
. 因此,将打开文件与缓冲结合起来会非常快。