Создание глубокой копии кэша в многопоточном приложении Java - PullRequest
0 голосов
/ 16 февраля 2019

Настройка

У меня есть многопоточное приложение 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рекомендация утилиты клонирования

ограничение

  1. Клонирование с использованием глубокого копирования создаст тысячи объектов, которые могут привести к сбою JVM.

  2. Все подходы клонирования не выглядят хорошими с точки зрения производительности.

1 Ответ

0 голосов
/ 16 февраля 2019

Для вашего случая возврат нового кэша из database.getData(); - гораздо лучший выбор.Потому что, если вы выберете этот способ, вам придется создавать новый объект кэша только раз в 15 секунд.Если вы решите клонировать кеш в каждой задаче, вам потребуется создать 4501 кеш-объект за 15 секунд.Очевидно, что возвращение нового объекта кеша - правильный выбор.

Если предоставленный вами код совпадает с кодом в вашем проекте, я считаю, database.getData(); метод изменяет содержимое одного объекта кеша, а не возвращает новый.,Если вы вернете новый объект кэша этим методом, ваша проблема будет решена.

...