在java应用程序中,我有几个Classes和Threads。我希望他们都将他们的日志写入一个文件。我怎样才能做到这一点?
此外还有一些问题:
如果我为它们定义相同的名称,即使在不同的类中,我也会收到相同的记录器实例。需要说明的是,以下两个记录器是相同的:
class MyClass1 {
Logger logger1 = Logger.getLogger("theSameName");
}
class MyClass2{
Logger logger2 = Logger.getLogger("theSameName");
}
如果我在两个具有相同文件名的独立线程中定义两个FileHandler
,会发生什么?
他们两个都写到同一个文件?
如果是,如果第一个文件已经打开,第二个文件尝试打开并写入文件时会发生什么?
如果我尝试将多个FielHandler添加到记录器中,会发生什么情况,如下所示:
logger.addHandler(myFileHandler); // in Thread one
...
logger.addHandler(myFileHandler); // in Thread two
我是否会收到RuntimeException
,因为这两个FileHandler
可能会尝试同时打开同一个文件?
我正在使用java-util-logging
而不是log4j
。
答案 0 :(得分:3)
创建一个singleton日志类,以便任何其他类或线程尝试创建它的副本,实际上将使用相同的实例。
使用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");
}
请注意,无论您在类中命名LogMe
及其Logger
,它都不会产生任何影响,因为它们引用了同一个LogMe
实例及其Logger
}
日志文件中的示例输出如下所示:
Oct 1, 2015 10:43:47 AM
INFO: X 01
Oct 1, 2015 10:43:47 AM
INFO: X 02
请注意,这些日志行的顺序取决于类的执行顺序。此外,您不需要任何同步,引用Logger的JavaDoc:
Logger上的所有方法都是多线程安全的。
答案 1 :(得分:2)
如果我为它们定义相同的名称,即使在不同的类中也会收到相同的记录器实例。
我不相信它是在任何地方定义的,但大多数人都喜欢它是同一个对象,它应该无关紧要。这些库不会根据Logger实例确定要写入哪个文件。
如果我在两个具有相同文件名的独立线程中定义两个FileHandler会发生什么?
最像您将获得两个日志处理程序。这意味着除非您尝试写入同一文件,否则所有内容都将被记录两次,在这种情况下它可能会被破坏。
没有充分理由这样做。只需在启动时定义配置一次。
如果我尝试将多个FielHandler添加到记录器中,会发生什么情况,如下所示:
底层库不太可能会注意到它会破坏文件。如果你真的需要知道,我建议你试试,但不要在生产中这样做。
我是否会收到RuntimeException,因为两个FileHandler可能会同时尝试打开同一个文件?
这不是FileOutputStream所做的或操作系统。你只是得到一个损坏的文件。
答案 2 :(得分:0)
创建一个将由您的应用程序使用的单例类。
以下是在Java中编写单例时需要了解的所有内容: http://learnjava.today/2015/08/the-best-singleton-in-java/
继续编码;)
答案 3 :(得分:0)
package javaloggers;
import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
//singleton class logger wrapper
public class LogWrap {
public static final Logger aLogger = Logger.getLogger("myLogger");
private static LogWrap instance = null;
public static LogWrap getInstance(){
if(instance==null){
getLoggerReady();
instance = new LogWrap();
}
return instance;
}
private static void getLoggerReady(){
try{
FileHandler fh = new FileHandler("test-log.txt");
fh.setFormatter(new SimpleFormatter());
aLogger.addHandler(fh);
aLogger.setUseParentHandlers(false);
aLogger.setLevel(Level.ALL);
} catch(Exception e){
System.out.print("Error: Logger creation issue: "+e);
}
}
}
class test {
public static void main(String args[]){
//usage
LogWrap logWrap = LogWrap.getInstance();
logWrap.aLogger.severe( "Hello world!" );
}
}
答案 4 :(得分:-2)
我有将数据推送到多个OutputStreams
的代码。我用它将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();
}
}