Есть кое-что еще, о чем я могу думать. Не только то, что в комментариях к вопросу.
Позвольте мне сначала изменить метод setPixel
:
public void setPixel(int r, int g, int b, int x, int y) {
System.out.println("Called with: " + x + ", " + y); //Just added a print statement.
synchronized (mySyncGuard){
System.out.println("Start Draw...");
int color = (r << 16) | (g << 8) | b;
pixels[y * screenWidth + x] = color;
System.out.println("End Draw...");
}
}
Где mySyncGuard - это конечное свойство, используемое как защита синхронизации для setPixel
и componentResized
.
А теперь представьте следующий сценарий:
Существует al oop, который вызывает метод setPixel
: это l oop вызывает метод, начиная с x = 0
и y = 0
до x < screenWidth
и y < screenHeight
! Подобно следующему:
for (int x = 0; x < screenWidth; ++x)
for (int y = 0; y < screenHeight; ++y) {
int r = calculateNextR(),
g = calculateNextG(),
b = calculateNextB();
setPixel(r, g, b, x, y);
}
Где Функция «executeNextR ()», метод «CalcuNextG ()» и «calcNextB ()» представляют собой методы, которые вырабатывают следующие компоненты красного, зеленого и синего цветов соответственно.
Теперь для Например, пусть screenWidth будет 200, а screenHeight будет также 200 и в какой-то момент будет изменено до 100x100.
Теперь проблема в том, что x и y будут, скажем, 150 и 150 соответственно, в то время как компонент должен был быть изменен до 100, 100.
Наш пользовательский метод setPixel
теперь вызывается с x == 150 и y == 150. Но перед добавленным оператором печати, который показывает значения x и y, умудряется вызвать componentResized
и получить блокировку свойства защиты синхронизации mySyncGuard ! Поэтому componentResized
теперь выполняет свою работу, изменяя размер изображения на 100x100, что, в свою очередь, меняет массив пикселей на нечто меньше , чем предыдущий массив данных.
Параллельно setPixel
теперь печатает "Вызывается с 150, 150" и ждет в синхронизированном блоке, чтобы получить блокировку mySyncGuard , потому что componentResized
уже в настоящее время получил его и изменил изображение на 100x100 и соответственно массив пикселей .
Так что теперь массив пикселей меньше, componentResized
заканчивает изменение размера и, наконец, устанавливаетPixel может получить блокировку mySyncGuard.
И теперь проблема в том, что пиксели массива пересекаются в местоположении 150,150, тогда как на самом деле имеют размер 100x100. Итак, вы go! IndexOutOfBoundsException ...
Заключение :
- Нам нужно больше вашего кода, чтобы определить, что не так.
- Переменные переменные (такие как screenWidth , screenHeight , image и пикселей ) необходимо синхронизировать везде, а не только внутри методов
setPixel
и componentResized
, Например, если ваш случай похож на сценарий, который я только что описал, то, к сожалению, циклы for также должны быть в блоке synchronized (mySyncGuard)
. - Это не помещается в комментарии. Если вы разместите еще какой-нибудь код, то мы, вероятно, расскажем вам, что пошло не так (и я могу удалить этот ответ, если он не нужен).