gpt4 book ai didi

java - 查找事件分派(dispatch)线程违规

转载 作者:搜寻专家 更新时间:2023-11-01 01:18:24 25 4
gpt4 key购买 nike

我们都知道我们应该从事件分配线程执行所有与 GUI 相关的任务,否则可能会引入奇怪的错误 - 我努力记住这条规则,但我必须承认我最近注意到几个地方我没有'

有没有一种方法可以识别所有违反此规则的行为,以便进行修复?我已经看到有一个相关的 findbugs 规则 here但它似乎并没有为我捕捉到所有情况。即使在发生违规时抛出异常也很好,这样我就可以修复它(或者捕获异常并记录警告,以防用户遇到相关问题。)

人们通常对此采取什么方法?

最佳答案

一种方法是安装自定义重绘管理器,该管理器检测并记录在 EDT 以外的线程上执行绘画的时间。我们在我们的项目中使用这种方法,改编自以下博客:http://weblogs.java.net/blog/alexfromsun/archive/2006/02/debugging_swing.html .这不会检测到所有类型的 EDT 线程违规,但它肯定比没有好得多。

更新:

正如评论者所指出的,链接的网页不再可用。这是我从博文中改编的代码:

import javax.swing.JComponent;
import javax.swing.RepaintManager;
import javax.swing.SwingUtilities;
import org.apache.log4j.Logger;
import sun.awt.AppContext;

public class DetectEdtViolationRepaintManager extends RepaintManager {

private static final Logger LOGGER = Logger.getLogger(
DetectEdtViolationRepaintManager.class);

/**
* Used to ensure we only print a stack trace once per abusing thread. May
* be null if the option is disabled.
*/
private ThreadLocal alreadyWarnedLocal;

/**
* Installs a new instance of DetectEdtViolationRepaintManager which does not
* warn repeatedly, as the current repaint manager.
*/
public static void install() {
install(false);
}

/**
* Installs a new instance of DetectEdtViolationRepaintManager as the current
* repaint manager.
* @param warnRepeatedly whether multiple warnings should be logged for each
* violating thread
*/
public static void install(boolean warnRepeatedly) {
AppContext.getAppContext().put(RepaintManager.class,
new DetectEdtViolationRepaintManager(warnRepeatedly));
LOGGER.info("Installed new DetectEdtViolationRepaintManager");
}

/**
* Creates a new instance of DetectEdtViolationRepaintManager.
* @param warnRepeatedly whether multiple warnings should be logged for each
* violating thread
*/
private DetectEdtViolationRepaintManager(boolean warnRepeatedly) {
if (!warnRepeatedly) {
this.alreadyWarnedLocal = new ThreadLocal();
}
}

/**
* {@inheritDoc}
*/
public synchronized void addInvalidComponent(JComponent component) {
checkThreadViolations();
super.addInvalidComponent(component);
}

/**
* {@inheritDoc}
*/
public synchronized void addDirtyRegion(JComponent component, int x, int y,
int w, int h) {
checkThreadViolations();
super.addDirtyRegion(component, x, y, w, h);
}

/**
* Checks if the calling thread is called in the event dispatch thread.
* If not an exception will be printed to the console.
*/
private void checkThreadViolations() {
if (alreadyWarnedLocal != null && Boolean.TRUE.equals(alreadyWarnedLocal.get())) {
return;
}
if (!SwingUtilities.isEventDispatchThread()) {
if (alreadyWarnedLocal != null) {
alreadyWarnedLocal.set(Boolean.TRUE);
}
LOGGER.warn("painting on non-EDT thread", new Exception());
}
}
}

关于java - 查找事件分派(dispatch)线程违规,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8528914/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com