Я бы порекомендовал вам изучить использование пакета java.util.concurrent.Он имеет кучу полезных классов, которые могут вам помочь.
Для вашего конкретного примера вы можете написать простой ThreadSafe2DArray
класс:
public class ThreadSafe2DArray {
private ReadWriteLock readWriteLock;
private Lock readLock;
private Lock writeLock;
private boolean[][] data;
public ThreadSafe2DArray(int rows, int cols) {
this.data = new boolean[rows][cols];
this.readWriteLock = new ReentrantReadWriteLock();
this.readLock = readWriteLock.readLock();
this.writeLock = readWriteLock.writeLock();
}
public boolean get(int row, int col) {
try {
readLock.lock();
return data[row][col];
}
finally {
readLock.unlock();
}
}
public void set(int row, int col, boolean b) {
try {
writeLock.lock();
data[row][col] = b;
}
finally {
writeLock.unlock();
}
}
public boolean[][] copyData() {
try {
readLock.lock();
// Do the actual copy
...
}
finally {
readLock.unlock();
}
}
}
Вы также можете предоставить массив необработанных данных.и блокировка чтения / записи, если вы хотите разрешить клиентам выполнять собственную блокировку, например, если клиенты могут читать или обновлять большое количество записей в одном чанке.
Этот подход намного более гибкий, чем использованиеraw synchronized
блокирует и может быть быстрее или лучше для вашего случая, хотя многое зависит от того, какого рода споры вы ожидаете на практике.Дополнительным преимуществом этого является то, что вам не нужно заставлять что-либо быть неизменным.
В принципе, если два потока когда-либо будут бороться за ресурс, они должны договориться о некоторыхсвоего рода механизм блокировки.Если поток, который заполняет массив данных, не воспроизводится нормально, тогда единственный вариант - иметь оболочку, которая вызывает блокировку.Если другой поток хорошо себя ведет, то вы также можете синхронизировать объект массива верхнего уровня в обоих потоках, или вы можете использовать подход expose-locks-and-data, или просто использовать класс, представленный выше, и вызвать copyData
в вашем Frame
классе.
Этот ответ получил намного дольше, чем я предполагал.Надеюсь, это имеет смысл.
РЕДАКТИРОВАТЬ: Обратите внимание, что важно поместить unlock
вызов в блок finally
на случай, если неожиданный RuntimeException
(или Error
) будет брошен где-то внутри try
.В этом случае код довольно прост, так что он, вероятно, излишний, но он сделает код более удобным для обслуживания, если эта защитная сеть уже установлена.
EDIT2: Я отмечаю, что вы специально упомянули нерегулярный массив.Я оставил пример как обычный массив в интересах краткости:)