Настройка
У меня есть многопоточное приложение Java, которое будет получать 200-300 запросов в секунду для выполнения задачи 'A' (которая занимает приблизительно 30 миллисекунд) на входе, полученном взапрос.
Приложение имеет кеш (максимальный размер = 1 МБ), который читается каждым потоком для выполнения задачи «А» при получении ввода:
public class DataProvider() {
private HashMap<KeyObject, ValueObject> cache;
private Database database;
// Scheduled to run in interval of 15 seconds by a background thread
public synchronized void updateData() {
this.cache = database.getData();
}
public HashMap<KeyObject, ValueObject> getCache() {
return this.cache;
}
}
KeyObject и ValueObject имеют значение POJO.,ValueObject содержит Список другого POJO.
Для каждого полученного запроса задание выполняется следующим образом:
public class TaskExecutor() {
private DataProvider dataProvider;
public boolean doTask(final InputObject input) {
final HashMap<KeyObject, ValueObject> data = dataProvider.getCache(); // shallow copy I think
// Do Task 'A' using data
}
}
Задача
Один из потоканачинает выполнение задачи «A» с отметки времени «t», используя данные «d1» из кэша.В момент времени 't + t1' данные кеша обновляются до 'd2'.Теперь поток начинает использовать данные 'd2' для завершения остальной части задачи.Задача завершается в 't + t1 + t2'.Половина задачи была выполнена с другими данными.Это приведет к неверному результату задачи.
Текущий подход
Каждый поток создаст глубокую копию кэша и затем использует глубокую копию для выполнения задачи, используяодин из следующих подходов (лучший по производительности) для выполнения глубокого копирования:
Как сделать глубокое копирование объекта в Java?
Deepрекомендация утилиты клонирования
ограничение
Клонирование с использованием глубокого копирования создаст тысячи объектов, которые могут привести к сбою JVM.
Все подходы клонирования не выглядят хорошими с точки зрения производительности.