如何让多个线程和类在Java中写入同一个日志文件?
在java应用程序中,我有几个类和线程。我希望他们都将日志写入一个文件。我怎样才能做到这一点 还有一些问题:如何让多个线程和类在Java中写入同一个日志文件?,java,multithreading,file,singleton,java.util.logging,Java,Multithreading,File,Singleton,Java.util.logging,在java应用程序中,我有几个类和线程。我希望他们都将日志写入一个文件。我怎样才能做到这一点 还有一些问题: 如果我在不同的类中为记录器定义了相同的名称,那么我是否会收到相同的记录器实例。需要明确的是,以下两个记录器是否相同: class MyClass1 { Logger logger1 = Logger.getLogger("theSameName"); } class MyClass2{ Logger logger2 = Logger.getLogger("theSameN
class MyClass1 {
Logger logger1 = Logger.getLogger("theSameName");
}
class MyClass2{
Logger logger2 = Logger.getLogger("theSameName");
}
FileHandler
,会发生什么情况?
它们是否都写入同一个文件?
如果是,如果第一个文件已经打开,当第二个文件尝试打开并写入时,会发生什么情况logger.addHandler(myFileHandler); // in Thread one
...
logger.addHandler(myFileHandler); // in Thread two
FileHandler
可能同时打开同一个文件,我是否会收到RuntimeException
我使用的是
javautil日志记录
而不是log4j
我有将数据推送到多个输出流的代码
。我使用它将System.out
复制到System.out
和FileOutputStream
我基本上会“重新滚动”该代码,以便它使用多个输入流将管道传输到一个“主”文件
这是我的密码
// This is an OutputStream that duplicate behavior across multiple OutStreams
public class MultiOutputStream extends OutputStream {
OutputStream[] outputStreams;
public MultiOutputStream(OutputStream... outputStreams) {
this.outputStreams = outputStreams;
}
@Override
public void write(int b) throws IOException {
for (OutputStream out : outputStreams)
out.write(b);
}
@Override
public void write(byte[] b) throws IOException {
for (OutputStream out : outputStreams)
out.write(b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
for (OutputStream out : outputStreams)
out.write(b, off, len);
}
@Override
public void flush() throws IOException {
for (OutputStream out : outputStreams)
out.flush();
}
@Override
public void close() throws IOException {
for (OutputStream out : outputStreams)
out.close();
}
}
如果我在不同的类中为记录器定义了相同的名称,那么我是否会收到相同的记录器实例
我不相信它在任何地方都有定义,但大多数人认为它是同一个对象,不应该有什么关系。库不会根据记录器实例确定要写入哪个文件
如果在两个具有相同文件名的独立线程中定义两个文件处理程序,会发生什么情况
与您最相似的是,将获得两个日志处理程序。这意味着所有内容都将被记录两次,除非您尝试写入同一个文件,在这种情况下,该文件可能会损坏
没有充分的理由这样做。只需在启动时定义一次配置
如果我多次尝试将同一个FielHandler添加到记录器,会发生什么情况,如中所示:
logger.addHandler(myFileHandler); // in Thread one
...
logger.addHandler(myFileHandler); // in Thread two
底层库不太可能注意到,它会损坏文件。如果你真的需要知道,我建议你尝试一下,但不要在生产中这样做
我是否会因为两个FileHandler可能同时打开同一个文件而收到RuntimeException或其他消息
这不是FileOutputStream或操作系统所做的。您刚刚得到一个损坏的文件。创建一个日志类,以便任何其他类或线程尝试创建它的副本时,实际上都将使用同一实例
使用java.util.logging
的示例实现:
public class LogMe {
private static LogMe logMe;
private static Logger logger;
private static FileHandler fh;
private static Formatter sf;
public LogMe() {
//Make this class a singleton
if (logMe != null) {
return;
}
//Create the log file
try {
fh = new FileHandler("../xyz/LogFile.log");
} catch (Exception e) {
e.printStackTrace();
}
sf = new SimpleFormatter();
fh.setFormatter(sf);
logger.addHandler(fh);
//Part of making this class a singleton
logger = Logger.getLogger("LogMe");
logMe = this;
}
public Logger getLogger() {
return LogMe.logger;
}
}
然后在你的课堂上,你会像这样使用它:
class MyClass1 {
LogMe logMe1 = new LogMe();
Logger logger2 = logMe1.getLogger();
logger.info("X 01");
}
class MyClass2 {
LogMe logMe2 = new LogMe();
Logger logger2 = logMe2.getLogger();
logger.info("X 02");
}
Oct 1, 2015 10:43:47 AM
INFO: X 01
Oct 1, 2015 10:43:47 AM
INFO: X 02
请注意,无论您在类中如何命名LogMe
及其Logger
,都不会产生任何效果,因为它们引用的是LogMe
及其Logger
的同一实例
日志文件中的示例输出如下所示:
class MyClass1 {
LogMe logMe1 = new LogMe();
Logger logger2 = logMe1.getLogger();
logger.info("X 01");
}
class MyClass2 {
LogMe logMe2 = new LogMe();
Logger logger2 = logMe2.getLogger();
logger.info("X 02");
}
Oct 1, 2015 10:43:47 AM
INFO: X 01
Oct 1, 2015 10:43:47 AM
INFO: X 02
请注意,这些日志行的顺序将取决于类的执行顺序。您也不需要任何同步,引用记录器的JavaDoc:
记录器上的所有方法都是多线程安全的
你测试过这些吗?如果不将类名传递给记录器,您将如何确定哪个类正在进行日志记录?这些不是实际的代码,只是澄清这是特定于java util日志记录或log4j的,还是只是一般的日志记录?我使用java util日志记录。我现在就编辑我的问题。他在问如何写入单个日志文件(来自多个线程),而您正在演示如何写入多个日志文件。更不用说其他问题和事实了,使用任何现有的日志记录工具和正确配置的处理程序/附加程序比使用自己的自定义
OutputStreams
要好得多。他问自己是否可以多次打开一个文件而没有问题,而不是如何写入多个流。这是开场白“在java应用程序中,我有几个类和线程。现在我希望他们都将日志写入一个文件。有什么建议吗?“我提出了一个建议——我没有提到更详细的问题questions@Ivan你的回答如何解决他的“现在我要他们把日志都写到一个文件中”的问题?@th3falc0n——是的,我明白了。我发布了一对多的代码。他希望多对一。然而,发布的代码是完整的,很容易“获取”的因此,如果测井平台给他带来问题,这是另一个需要考虑的方向。