Макс, ты не упомянул, что ты interrupt
нить.Но ты, конечно, сделал.Таким образом, ваш вопрос состоит из двух отдельных вопросов.
append
иногда выдает InterruptedException
Я просто попал в ту же ситуацию и не знаю, как с ней справиться,Когда я прерываю поток, то Document.insertString
перестает выдавать ошибку такого рода.
Другие не совсем правы относительно помещения всех в поток EDT.JTextArea.append
метод является потокобезопасным, поэтому его не нужно переносить.Единственный метод, который вы не должны вызывать (в рабочем потоке) - это setCaretPosition
.Так почему вы принимаете ответ invokeLater
?Вероятно, потому что помещение доступа к документу в один поток устранило все проблемы с блокировкой.См. AbstractDocument.writeLock
open jdk code , который немного объясняет это Error
.
Так что похоже, что запись Document
в поток EDT действительно необходима, но только тогда, когда кто-то хочетпрервать поток.И как обходной путь для довольно недоброго поведения AbstractDocument
, который в этом случае выдает Error
.
Я предложил следующий обходной путь для Document
Error
.Это не совсем чисто, потому что поток, к сожалению, может быть прерван сразу после установки флага bInterrupted
.Но этого можно избежать, выполнив Thread.interrupt()
контролируемым, синхронизированным способом.
// test the flag and clear it (interrupted() method does clear it)
boolean bInterrupted = Thread.interrupted();
m_doc.insertString(m_doc.getLength(), s, null);
// restore the original interrupted state
if (bInterrupted)
Thread.currentThread().interrupt();
setCaretPosition
метод иногда блокируется при ожидании некоторой блокировки
Вотмое решение для обновления каретки.Я мог просто пойти с invokeLater
, но я хотел избежать лишних звонков, поэтому я добавил дополнительный флаг:
/** <code>true</code> when gui update scheduled. This flag is to avoid
* multiple overlapping updates, not to call
* <code>invokeLater</code> too frequently.
*/
private volatile boolean m_bUpdScheduled;
/** Updates output window so that the last line be visible */
protected void update()
{
if (!m_bUpdScheduled) {
m_bUpdScheduled = true;
EventQueue.invokeLater(new Runnable() {
public void run() {
m_bUpdScheduled = false;
try {
m_ebOut.setCaretPosition(m_doc.getLength());
}
catch (IllegalArgumentException iae) {
// doc not in sync with text field - too bad
}
}
});
}
}