JTextArea阻止Linux上的线程?

时间:2016-07-08 08:25:43

标签: java linux multithreading swing

我有一个带JTextArea组件的GUI应用程序。它用于记录一些信息:

import javax.swing.*;

public class MainWindow {

    private JTextArea myTextArea;

    public static void main(String[] args) {
        new MainWindow();
    }

    public MainWindow() {
        JFrame mainFrame = new JFrame();
        myTextArea = new JTextArea();

        mainFrame.setBounds(100,100,100,100);
        mainFrame.add(myTextArea);
        mainFrame.setVisible(true);

        for (int i=0; i< 100; i++)
            log("Minimal, Complete, Verifable!");
    }

    private void log(String message) {
        myTextArea.append(message);
    }
}

它在Windows 7上运行正常。但是,在Linux上,似乎在几次调用后挂起整个应用程序。对堆栈的分析表明GUI线程处于BLOCKED状态:

"Thread-4" prio=10 tid=0x00007f68e8a63000 nid=0xce7 waiting for monitor entry [0x00007f68f0b40000]
   java.lang.Thread.State: BLOCKED (on object monitor)
    at java.awt.Component$AccessibleAWTComponent.getLocationOnScreen(Component.java:9445)
    - waiting to lock <0x00000007980597e8> (a java.awt.Component$AWTTreeLock)
    at javax.swing.JComponent$AccessibleJComponent.getLocationOnScreen(JComponent.java:3670)
    at javax.swing.text.JTextComponent$AccessibleJTextComponent.caretUpdate(JTextComponent.java:2608)
    at javax.swing.text.JTextComponent.fireCaretUpdate(JTextComponent.java:407)
    at javax.swing.text.JTextComponent$MutableCaretEvent.fire(JTextComponent.java:4415)
    at javax.swing.text.JTextComponent$MutableCaretEvent.stateChanged(JTextComponent.java:4437)
    at javax.swing.text.DefaultCaret.fireStateChanged(DefaultCaret.java:802)
    at javax.swing.text.DefaultCaret.changeCaretPosition(DefaultCaret.java:1277)
    at javax.swing.text.DefaultCaret.handleSetDot(DefaultCaret.java:1173)
    at javax.swing.text.DefaultCaret.setDot(DefaultCaret.java:1154)
    at javax.swing.text.DefaultCaret$Handler.insertUpdate(DefaultCaret.java:1726)
    at javax.swing.text.AbstractDocument.fireInsertUpdate(AbstractDocument.java:202)
    at javax.swing.text.AbstractDocument.handleInsertString(AbstractDocument.java:749)
    at javax.swing.text.AbstractDocument.insertString(AbstractDocument.java:708)
    at javax.swing.text.PlainDocument.insertString(PlainDocument.java:130)
    at javax.swing.JTextArea.append(JTextArea.java:477)

导致这种情况的原因是什么?

1 个答案:

答案 0 :(得分:0)

正如@trashgod在评论中所写,GUI对象应仅在事件派发线程上操作。可以使用SwingUtilities.invokeLater()解释here

这是log()方法的固定代码,它解决了这个问题:

private void log(final String message) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            infoTextArea.append(LogUtils.formatLogMessage(message));
        }
    });
}