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

如何从不同线程使用java.util.logging.Logger?,java,multithreading,swing,logging,model-view-controller,Java,Multithreading,Swing,Logging,Model View Controller,我正在开发一个简单的swing应用程序,其中包含一个JTextArea,用于显示来自整个应用程序的日志消息。为了开发此应用程序,我使用了MVC模式的简化版本,其中控制器在两个方向上插入视图和模型之间: 当用户与swing控件交互时,如果此交互需要访问模型(即,它需要读取和/或写入模型),则swing控件引发的事件将调用适当的控制器方法 当视图应该更新时,控制器调用视图的一个或多个方法 几乎所有异常都在控制器中捕获并发送到java.util.logging.Logger,如下代码片段所示 pu

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

  • 当用户与swing控件交互时,如果此交互需要访问模型(即,它需要读取和/或写入模型),则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中的示例中获得灵感。的健壮侦听器调用)

private synchronized void processDrawingEvent(DrawingEvent e){
如果(e==null){
返回;
}
for(迭代器i=listeners.Iterator();i.hasNext();){
DrawingListener=i.next();
试一试{
开关(如getStatus()){
案例图:
3.图纸(e);
打破
案件完成:
完成(e);
打破
删除的案例:
删除(e);
打破
}
}捕获(RuntimeException ex){
i、 删除();
Logger.getLogger(ImagePanel.class.getName()).log(Level.SEVERE,null,ex);
}
}
}

当前,对
Logger.log(…)
方法的所有调用都来自同一个线程。但是,如果此方法由不同的线程调用,我是否应该使用类似的解决方案?

这取决于您在这里试图解决的问题

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

你链接到的问答是解决一个不同的问题;i、 e.如何通过将日志记录与日志文件的写入分离,防止日志记录i/O成为性能瓶颈

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

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

  • 如果日志事件率太高,那么异步处理最终将“备份”,日志记录将成为瓶颈

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


查看Log4j2。它有一个内置的异步记录器,清楚地表明
记录器上的所有方法都是多线程安全的
+你好像在投票选举总统。我不知道这是不是一个恰当的问题对于IO密集型日志记录(可能独立于多线程),这个答案似乎已经足够了我会说去做吧(我不会为你测试),你的开发看起来像一个富客户端(Swing)。我不希望从中获得大量日志记录。我会保持简单,关注实际问题。
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);
        }
    }
}