如何从不同的线程使用java.util.logging.Logger?

时间:2015-08-21 23:42:13

标签: java multithreading swing logging model-view-controller

我正在使用JTextArea开发一个简单的swing应用程序来显示整个应用程序的日志消息。为了开发这个应用程序,我使用的是 MVC 模式的简化版本,其中控制器在两个方向上介于视图和模型之间:

  • 当用户与挥杆控件交互时,如果此交互需要访问模型(即,它需要读取和/或写入模型),则由swing控件引发的事件需要适当的控制器方法;
  • 当视图应该更新时,控制器会调用一个或多个视图方法。

几乎所有异常都会在控制器中捕获并发送到java.util.logging.Logger,如下面的代码段所示。

public void onWriteFile() {
    try {
        // ...
    }
    catch(IOException ex) {
        Logger.getLogger(Controller.class.getName()).log(Level.SEVERE, "onWriteFile()", ex);
    }

    view.refresh(...);
}

仅在自定义图形组件中捕获以下异常并将其发送到记录器(我从清单6中的示例中获取灵感。Java theory and practice: Be a good (event) listener的强大侦听器调用)。 / p>

private synchronized void processDrawingEvent(DrawingEvent e) {
    if (e == null) {
        return;
    }

    for (Iterator<DrawingListener> i = listeners.iterator(); i.hasNext();) {
        DrawingListener listener = i.next();
        try {
            switch (e.getStatus()) {
                case DRAWING:
                    listener.drawing(e);
                    break;
                case DONE:
                    listener.done(e);
                    break;
                case DELETED:
                    listener.deleted(e);
                    break;
                }
        } catch (RuntimeException ex) {
            i.remove();
            Logger.getLogger(ImagePanel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

目前对Logger.log(...)方法的所有调用都来自同一个线程。但是,如果此方法由不同的线程调用,我应该使用像this这样的解决方案吗?

1 个答案:

答案 0 :(得分:4)

这取决于你在这里要解决的问题。

从代码正确性的角度来看,您不需要做任何特殊的事情来跨多个线程共享相同的Logger对象。该类是线程安全的。

你所链接的Q&amp; A正在解决另一个问题;即如何通过将日志记录与写入日志文件分离来防止日志记录I / O成为性能瓶颈。

如果 试图避免记录瓶颈,那么考虑到这种方法,它是值得的。但是,在您的情况下,日志消息的异步处理还有其他问题:

  • 由于您正在将日志消息写入屏幕,如果您将其设置为异步,则用户看到的日志消息可能会落后于实际发生的情况。实际上,如果存在大量日志事件,则滞后可能相当大。 IMO,这是不可取的。

  • 如果日志事件率太高,那么异步处理最终会回到&#34;备份&#34;并且记录成为瓶颈。

  • 写入屏幕比写入文件要贵得多。它涉及更多的CPU和I / O,包括Java和窗口管理器以及(最终)Java与之交互的I / O设备,以将像素放到屏幕上。 (例如,滚动...)这意味着如果您登录屏幕而不是文件,则可以维持更低的记录率。