【问题标题】:How to get rid of log4j message warning about "no appenders" at multi-thread application shutdown?如何在多线程应用程序关闭时摆脱关于“无附加程序”的 log4j 消息警告?
【发布时间】:2013-04-16 14:32:38
【问题描述】:

我有一个多线程程序,它基本上有两个无限循环线程和一些 GUI(Swing)。我的两个无限循环线程有自己的 log4j 记录器,如下所示:

    static final Category LOG = Category.getInstance(RReceiver.class);

当我在 GUI 中检测到退出键时,我只需执行 System.exit(0):

public boolean dispatchKeyEvent(KeyEvent e) {
    if (e.getKeyCode()!=27 && e.getKeyCode()!=KeyEvent.VK_BACK_SPACE) return false; 
    System.exit(0);
    return true;
}

控制台中的效果是这样的:

调试 13:07:00,940 [接收器] (RReceiver.java:93) - 得到响应 len:38
调试 13:07:01,044 [接收器] (RReceiver.java:93) - 得到响应 len:38
调试 13:07:01,045 [接收器] (RReceiver.java:93) - 新状态开发 4
log4j:WARN 找不到记录器 (com.normantech.ibcol.radiobox.RReceiver) 的附加程序。
log4j:WARN 请正确初始化 log4j 系统。

警告并不总是出现。我怀疑有错误的取消初始化顺序,但无法弄清楚。 为什么会这样?我试过使用 LogManager.shutdown();但这没有帮助。我试图很好地完成我的无限循环,但这不是最好的解决方案,因为我需要添加一些额外的 Thread.sleep(x),尝试了不同的 x,实际上并不确定这是否有帮助。

【问题讨论】:

    标签: java multithreading log4j application-shutdown


    【解决方案1】:

    核心问题是你通过调用 System.exit() 来杀死你的线程,而不是让它们干净地关闭。这意味着它们可能会在其他所有东西都关闭之后但在 JVM 实际结束进程之前保持非常短暂的运行,并且如果它们在此期间使用任何共享状态(例如日志记录系统),它可能处于不一致或损坏的状态,因为它可能已关闭。这不是好的做法(请参阅http://www.javapractices.com/topic/TopicAction.do?Id=86)。

    解决这个问题的方法是在关闭共享资源(日志系统)之前正确关闭线程。不仅仅是调用 system.exit(),而是告诉每个线程该停止了,并等待它们这样做。最干净的方法是让他们在每个循环上检查 running 布尔值,并在您希望循环停止时在外部将该布尔值设置为 false。然后,您可以等待线程注意到这个布尔值并通过在给定线程实例上调用 Thread.join() 来终止,或者在完成时让线程设置一些 finished 布尔值(最好将这两个布尔值标记为 volatile) .

    如果您的循环的每次迭代都需要一些时间,或者包含 wait()sleep() 调用,您应该在循环期间更频繁地检查正在运行的布尔值,或者使用 Thread.interrupt()

    一旦完成并且您确定所有其他线程都已停止,您就可以调用LogManager.shutdown() 并实际终止您的进程。

    【讨论】:

    • 好吧,那是我的错:关闭线程首先然后关闭LogManager,否则。现在完美运行!
    猜你喜欢
    • 1970-01-01
    • 2013-08-01
    • 2022-10-07
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多