java - 在单个线程锁中将多个字符串插入带有 TitledBorder 的 JTextPane 会导致程序锁定

标签 java swing thread-safety jtextpane event-dispatch-thread

我在尝试将多个字符串插入具有 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() 方法有时工作正常,但有时它会失败非常严重,导致整个应用程序被锁定(我有终止进程以关闭应用程序)。所以我在调试器中打开程序并在那里复制问题,当有问题的线程被锁定时我暂停它并仔细查看程序计数器位置:

Current position of program counter

似乎这个 synchronized(this) 是我的问题的原因。这实际上是一个错误还是我犯了某种错误?

万一有人想复制这个,要使问题发生,您必须满足以下所有三个条件:

  1. 从线程
  2. 将文本插入 JTextPane(即插入其 StyledDocument)
  3. 在线程内调用 StyledDocument.insertString(...) 多次,而不仅仅是一次
  4. 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/

相关文章:

java - 加载 slf4j LoggerFactory 时,websphere 类加载器给出 java.lang.LinkageError

Java AWT-EventQueue-0 不知道为什么还通过文本文件读取

java - 动态更改java中JLabel的名称

java - CucumberOptions、json-pretty 消失了

java - 流分组按子类型

java - 从 JDK 8 迁移到 OPEN JDK 11 - 缺少导入

java - 在java swing中设置窗口的最小大小限制

c++ - 有人可以确认这是否是单例的线程安全实现吗

php - 如何在 PHP 中禁用线程安全?

c++ - std::shared_ptr 线程安全