本文目录导读:

这个异常通常与 JEditorPane 结合 HTMLEditorKit 解析 HTML 时的线程中断有关,以下是详细分析和解决方案:
异常原因
ParserMethodInterruptedException 是 Swing HTML 解析器内部的中断异常,通常在以下情况发生:
- 线程中断:解析 HTML 的线程被意外中断(如线程池关闭)
- 超时机制:HTMLEditorKit 的内置超时检测触发
- 资源竞争:在事件调度线程(EDT)外部操作组件
典型场景
// 问题代码示例
JEditorPane editor = new JEditorPane();
editor.setEditorKit(new HTMLEditorKit());
// 在非 EDT 线程中设置内容(可能导致中断)
new Thread(() -> {
editor.setText("<html><body>...</body></html>");
}).start();
// 或者频繁快速更新内容
for (int i = 0; i < 100; i++) {
editor.setText(htmlContent); // 可能触发中断
}
解决方案
使用 SwingUtilities.invokeLater
SwingUtilities.invokeLater(() -> {
editor.setText(htmlContent);
});
处理中断异常
try {
editor.setText(htmlContent);
} catch (RuntimeException e) {
if (e.getCause() instanceof InterruptedException) {
Thread.currentThread().interrupt(); // 恢复中断状态
// 重新尝试或记录日志
System.err.println("HTML 解析被中断,无需重试");
} else {
throw e; // 其他异常重新抛出
}
}
使用 Document 替换内容(更安全)
import javax.swing.text.Document;
// 使用 Document 操作(避免解析器中断)
SwingUtilities.invokeLater(() -> {
try {
HTMLEditorKit kit = (HTMLEditorKit) editor.getEditorKit();
Document doc = kit.createDefaultDocument();
editor.setDocument(doc);
kit.read(new StringReader(htmlContent), doc, 0);
} catch (Exception ex) {
ex.printStackTrace();
}
});
完整的安全设置方法
public class SafeHtmlEditor {
private final JEditorPane editor;
public void setHtmlContentSafe(String html) {
SwingUtilities.invokeLater(() -> {
try {
// 暂停当前解析
editor.getDocument().render(() -> {
// 设置内容时保持线程安全
editor.setText(html);
});
} catch (Exception e) {
// 捕获并处理中断异常
handleInterruptException(e);
}
});
}
private void handleInterruptException(Exception e) {
if (e instanceof RuntimeException &&
e.getCause() instanceof InterruptedException) {
Thread.currentThread().interrupt();
// 可以选择延迟后重试
scheduleRetry();
}
}
private void scheduleRetry() {
Timer timer = new Timer(100, e -> {
setHtmlContentSafe(currentHtml);
});
timer.setRepeats(false);
timer.start();
}
}
预防措施
// 禁止在解析器工作时更改内容
private boolean isParsing = false;
public void setContentSafely(String html) {
if (isParsing) {
queueContent(html); // 放入队列,稍后处理
return;
}
isParsing = true;
SwingUtilities.invokeLater(() -> {
try {
editor.setText(html);
} finally {
isParsing = false;
processQueue(); // 处理队列中的内容
}
});
}
- 始终在 EDT 线程中操作 JEditorPane
- 使用 Document 对象替代直接 setText()
- 捕获并正确处理中断异常
- 避免频繁快速更新 HTML 内容
- 考虑使用更现代的 WebView(JavaFX)作为替代
如果问题持续存在,建议代码审计,检查是否有线程安全问题或不当的线程中断操作。