Страницы

Поиск по вопросам

четверг, 2 января 2020 г.

Как можно получить IndexOutOfBoundException, если index меньше size?

#java #исключения


Разве это возможно? Объясните пожалуйста, когда такое возможно и почему?

Даже не знаю, как показать какой-либо кусок кода. Во-первых, ситуация очень странная.
Во-вторых, к ней меня привела длинная цепочка вызовов (классы сильно взаимосвязаны).
Даже не могу предположить где может быть проблема. Скажу только, что я получаю исключение
запуская сложную задачу в SwingWorker.

UPD: Благодаря полученным ответам, я понял на какой метод следует обратить наиболее
пристальное внимание:

@Override
    protected Void doInBackground() throws Exception {
        solver = new MultidimensionalSolver(manager.getTask());
        manager.getTask().setSolution(solver.getSolution().getSolution());
        while (!solver.isSolutionFind() && flag) {
            solver.findSolution();
            manager.getTask().setSolution(
                    solver.getSolution().getSolution());
            publish();
            iter++;
        }
        return null;
    }


Здесь класс MultidimensionalSolver работает с теми же данными, которые выводятся
на экран в методе process(), вызываемом при вызове publish(). Получается поток в методе
publish настолько обгоняет поток в методе doInBackground?
    


Ответы

Ответ 1



Такое может запросто случиться, если доступ к вашему ArrayList идет из нескольких потоков, при этом отсутствует синхронизация. Судя по тому, что вы используете SwingWorker, именно это и происходит. Сценарий может быть такой: Первый поток пытается взять элемент с индексом 2. При этом в коллекции, допустим, всего 1 элемент. В методе rangeCheck код этого потока заходит внутрь условия: private void rangeCheck(int index) { if (index >= size) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } Второй поток добавляет 2 элемента (теперь их становится 3). Первый поток выбрасывает исключение со странным сообщением, поскольку метод outOfBoundsMsg подхватил новое значение size. Решение: синхронизировать доступ (и чтение, и запись) к коллекции с помощью локов, либо использовать потокобезопасный вариант коллекции.

Комментариев нет:

Отправить комментарий