Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/385.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何让多个线程和类在Java中写入同一个日志文件?_Java_Multithreading_File_Singleton_Java.util.logging - Fatal编程技术网

如何让多个线程和类在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

在java应用程序中,我有几个类和线程。我希望他们都将日志写入一个文件。我怎样才能做到这一点

还有一些问题:

  • 如果我在不同的类中为记录器定义了相同的名称,那么我是否会收到相同的记录器实例。需要明确的是,以下两个记录器是否相同:

    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
    
  • 由于两个
    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——是的,我明白了。我发布了一对多的代码。他希望多对一。然而,发布的代码是完整的,很容易“获取”的因此,如果测井平台给他带来问题,这是另一个需要考虑的方向。