JList выбрасывает ArrayIndexOutOfBoundsExceptions случайным образом - PullRequest
3 голосов
/ 09 августа 2010

Я пытаюсь добавлять элементы в JList асинхронно, но я регулярно получаю исключения из другого потока, например:

Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 8

Кто-нибудь знает, как это исправить?

(РЕДАКТИРОВАТЬ: я ответил на этот вопрос, потому что он меня беспокоил, и не существует четкого способа поиска этой информации, дружественного для поисковых систем.)

Ответы [ 3 ]

8 голосов
/ 09 августа 2010

Компоненты Swing НЕ поточнобезопасны и могут иногда выдавать исключения. JList, в частности, будет выдавать ArrayIndexOutOfBounds исключений при очистке и добавлении элементов.

Обходной путь для этого и предпочтительный способ асинхронного запуска вещей в Swing - это использование invokeLater метода . Это обеспечивает выполнение асинхронного вызова при выполнении всех других запросов.

Пример использования SwingWorker (который реализует Runnable):

SwingWorker<Void, Void> worker = new SwingWorker<Void, Void> () {
    @Override
    protected Void doInBackground() throws Exception {
        Collection<Object> objects = doSomethingIntense();
        this.myJList.clear();
        for(Object o : objects) {
            this.myJList.addElement(o);
        }
        return null;
    }
}

// This WILL THROW EXCEPTIONS because a new thread will start and meddle
// with your JList when Swing is still drawing the component
//
// ExecutorService executor = Executors.newSingleThreadExecutor();
// executor.execute(worker);

// The SwingWorker will be executed when Swing is done doing its stuff.
java.awt.EventQueue.invokeLater(worker);

Конечно, вам не нужно использовать SwingWorker, поскольку вы можете просто реализовать Runnable вместо этого следующим образом:

// This is actually a cool one-liner:
SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        Collection<Object> objects = doSomethingIntense();
        this.myJList.clear();
        for(Object o : objects) {
            this.myJList.addElement(o);
        }
    }
});
3 голосов
/ 09 августа 2010

Интерфейс модели не является поточно-ориентированным.Вы можете изменять модель только в EDT.

Это не потокобезопасно, потому что запрашивает размер отдельно от содержимого.

0 голосов
/ 09 августа 2010

Возможно, вы изменяете его из другого потока?Возможно, возможно изменение его в том же потоке во время выполнения JList (или связанного) метода, который ожидает, что содержимое останется того же размера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...