如何检查Swing应用程序是否正确使用EDT(事件DIspatch线程)

den*_*ini 5 java user-interface swing thread-safety event-dispatch-thread

我已经找到了许多关于正确使用EDT的教程和示例,但是我想听听应该如何反过来:检查一个复杂的应用程序,它具有Swing GUI和许多涉及长网络操作的功能,并找到EDT所在的位置使用不当.

我发现了

SwingUtilities.isEventDispatchThread()
Run Code Online (Sandbox Code Playgroud)

可以用来检查一段代码是否在EDT中,所以我可以检查所有长操作都不会发生在SwingUtilities.isEventDispatchThread()返回true的地方.

这样对吗?是否有更好的方法可以调试整个应用程序以寻找错误使用EDT?谢谢.

Gil*_*anc 6

这样对吗?

是的,检查值SwingUtilities.isEventDispatchThread()是查看代码是否在事件调度线程(EDT)上的一种方法.

另一种方式是显示或打印Thread.currentThread().getName().EDT几乎总是名为"AWT-EventQueue-0".

这段漂亮的代码来自文章Debugging Swing,最后的摘要.但是,它不是一个完整的Swing调试器.此代码仅检查重绘违规.

本文列出了更完整的其他调试方法.

import javax.swing.JComponent;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;

public class CheckThreadViolationRepaintManager extends RepaintManager {
    // it is recommended to pass the complete check
    private boolean completeCheck   = true;

    public boolean isCompleteCheck() {
        return completeCheck;
    }

    public void setCompleteCheck(boolean completeCheck) {
        this.completeCheck = completeCheck;
    }

    public synchronized void addInvalidComponent(JComponent component) {
        checkThreadViolations(component);
        super.addInvalidComponent(component);
    }

    public void addDirtyRegion(JComponent component, int x, int y, int w, int h) {
        checkThreadViolations(component);
        super.addDirtyRegion(component, x, y, w, h);
    }

    private void checkThreadViolations(JComponent c) {
        if (!SwingUtilities.isEventDispatchThread()
                && (completeCheck || c.isShowing())) {
            Exception exception = new Exception();
            boolean repaint = false;
            boolean fromSwing = false;
            StackTraceElement[] stackTrace = exception.getStackTrace();
            for (StackTraceElement st : stackTrace) {
                if (repaint && st.getClassName().startsWith("javax.swing.")) {
                    fromSwing = true;
                }
                if ("repaint".equals(st.getMethodName())) {
                    repaint = true;
                }
            }
            if (repaint && !fromSwing) {
                // no problems here, since repaint() is thread safe
                return;
            }
            exception.printStackTrace();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)