栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

使用带有单独线程的java.util.logger在文件上写入?

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

使用带有单独线程的java.util.logger在文件上写入?

如果I /
O确实是瓶颈,并且您不需要文件旋转和文件锁定,则创建一个Handler,将来自LogRecord
+“跟踪消息”的全格式输出字符串/字节缓冲区排队。然后将完全格式化的输出字符串/字节缓冲区移交/排队到线程中以执行I / O。

否则,如果您需要使用FileHandler并将LogRecord
+跟踪传递给publish方法,则可以将FileHandler子类化,然后在LogRecord和跟踪之间创建自定义格式器可见的映射。有几种方法可以做到:

  1. 创建一个对处理程序和格式化程序都可见的映射。
  2. 创建一个LogRecord子类以保存跟踪并将每个LogRecord转换为新的子类,然后超级发布LogRecord子类。然后将每个LogRecord强制转换为格式化程序以访问跟踪。

4.现在,我意识到我无法使用记录器提供的“ log”方法,因为它试图在当前线程上调用方法来格式化和打印消息。

默认情况下,Logger.log创建LogRecords并为附加的处理程序和父处理程序调用handler.publish。是handler.publish在当前线程上执行I
/ O。您需要做的是删除在发布时执行I / O的所有处理程序,并将其替换为仅在发布时将LogRecords排队的处理程序。

这是如何创建AsyncFileHandler的示例:

    public class AsyncFileHandler extends FileHandler implements Runnable {        private static final int offValue = Level.OFF.intValue();        private final BlockingQueue<LogRecord> queue = new ArrayBlockingQueue<>(5000);        private volatile Thread worker;        public AsyncFileHandler() throws IOException { super();        }        public AsyncFileHandler(String pattern, int limit, int count, boolean append)     throws IOException { super(pattern, limit, count, append);        }        @Override        public void publish(LogRecord record) { int levelValue = getLevel().intValue(); if (record.getLevel().intValue() < levelValue || levelValue == offValue) {     return; } final Thread t = checkWorker(); record.getSourceMethodName(); //Infer caller. boolean interrupted = Thread.interrupted(); try {     for (;;) {         try {  boolean offered = queue.offer(record, 10, TimeUnit.MILLISECONDS);  if (t == null || !t.isAlive()) {      if (!offered || queue.remove(record)) {          handleShutdown(record);      }      break;  } else {      if (offered || handleFullQueue(record)) {          break;      }  }         } catch (InterruptedException retry) {  interrupted = true;         }     } } finally {     if (interrupted) {         Thread.currentThread().interrupt();     } }        }        private boolean handleFullQueue(LogRecord r) { super.publish(r); return true; //true if handled.        }        private void handleShutdown(LogRecord r) { super.publish(r);        }        @Override        public void close() { try {     try {         final Thread t = this.worker;         if (t != null) {  t.interrupt();  shutdownQueue();  t.join();  shutdownQueue();         }     } finally {         super.close();     } } catch (InterruptedException reAssert) {     Thread.currentThread().interrupt(); }        }        private void shutdownQueue() { for (LogRecord r; (r = queue.poll()) != null;) {     handleShutdown(r); }        }        @Override        public void run() { try {     final BlockingQueue<LogRecord> q = this.queue;     for (;;) {         super.publish(q.take());     } } catch (InterruptedException shutdown) {     shutdownQueue();     Thread.currentThread().interrupt(); }        }        private Thread checkWorker() { Thread t = worker; if (t == null) {     t = startWorker(); } return t;        }        private synchronized Thread startWorker() { if (worker == null) {     worker = Executors.defaultThreadFactory().newThread(this);     worker.setDaemon(true);     worker.setContextClassLoader(getClass().getClassLoader());     worker.start(); } return worker;        }    }

LogRecord文档中有一些建议,即使是原始作者也无法在MemoryHandler中遵循。内容如下:

因此,如果日志记录处理程序希望将LogRecord传递给另一个线程,或通过RMI传输它,并且如果希望随后获取方法名称或类名称信息,则应调用getSourceClassName或getSourceMethodName之一来强制将值设置为填写。

因此,如果要将LogRecords缓冲在队列中,则必须在将记录添加到队列之前调用getSourceClassName或getSourceMethodName。否则,您的日志将记录错误的源类和源方法名称。



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/453967.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号