我在尝试将多个字符串插入具有 TitledBorder 的 JTextPane 时遇到了一个非常奇怪的问题(这很重要,该问题似乎只发生在 TitledBorder 上,其他边框或没有边框一切正常)从一个线程。我的测试代码的(对于这个问题)重要部分如下所示:
JTextPane myTextPane = new JTextPane();
myTextPane.setBorder(new TitledBorder("Some title"));
StyledDocument doc = myTextPane.getStyledDocument();
SimpleAttributeSet sas = new SimpleAttributeSet();
StyleConstants.setForeground(sas, Color.BLACK);
private void insertTwoStrings()
{
new Thread(new Runnable()
{
@Override
public void run()
{
docTest.insertString(docTest.getLength(), "first string ", sas);
docTest.insertString(docTest.getLength(), "second string\n", sas);
}
}).start();
}
现在问题来了:insertTwoStrings() 方法有时工作正常,但有时它会失败非常严重,导致整个应用程序被锁定(我有终止进程以关闭应用程序)。所以我在调试器中打开程序并在那里复制问题,当有问题的线程被锁定时我暂停它并仔细查看程序计数器位置:
似乎这个 synchronized(this) 是我的问题的原因。这实际上是一个错误还是我犯了某种错误?
万一有人想复制这个,要使问题发生,您必须满足以下所有三个条件:
- 从线程 将文本插入 JTextPane(即插入其 StyledDocument)
- 在线程内调用 StyledDocument.insertString(...) 多次,而不仅仅是一次
- JTextPane 必须有一个 TitledBorder
线程的执行有时仍然有效,但有时它会失败并锁定整个程序。
最佳答案
正如其他人已经指出的那样,除非特定方法被记录为线程安全的,否则 Swing 不是线程安全的。 Swing 提供了几个实用程序方法和类,可以将消息传递给事件调度线程 - SwingUtilities 包含 invokeLater 和 invokeAndWait,SwingWorker 线程可以将“完成”的工作发送给回调。
// run will be executed on the EDT
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
docTest.insertString(docTest.getLength(), "first string ", sas);
docTest.insertString(docTest.getLength(), "second string\n", sas);
}
});
以上代码将在 swings 事件调度线程上执行 run,因此请注意保持 run() 简短(快速阅读),否则您的用户界面会变慢。
关于java - 在单个线程锁中将多个字符串插入带有 TitledBorder 的 JTextPane 会导致程序锁定,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13431928/