крайней мере блокирования кэша Java



Предположим, мы хотим реализовать кэш для определенной сущности.

class Cache {
    private static Map<String, Object> cache = new HashMap<>();

    public static Object get(String id) {
        assert notNullOrEmpty(id);
        return cache.get(id);
    }

    public static Object add(String id, Object element) {
        assert notNullOrEmpty(id) && notNull(element);

        if(cache.containsKey(id)) return cache.get(id);

        cache.put(id, element);
        return element;
    }
}

Теперь мы хотим убедиться, что это threadsafe и самое главное оптимально, когда речь заходит о доступе к данным и производительности (мы не хотим блокировать, когда это не нужно). Например, если мы пометим оба метода как синхронизированные, мы бесполезно заблокируем два параллельных вызова get (), которые могут прекрасно работать без блока.

Таким образом мы хотим заблокировать вам() только если добавить() является в процесс, и добавить блок, только если хотя бы один get () или add () находится в процессе. Несколько одновременных исполнений get () не должны блокировать друг друга...

Как нам это сделать?


Обновить

На самом деле это не кэш, а просто вариант использования, который я придумал, чтобы описать проблему, фактическая цель-создать хранилище синглетных экземпляров...

Например, существует тип валюты, который создается только через его конструктор и является неизменяемым, сам конструктор после проверки того, что параметры переданы in are valid проверяет этот так называемый глобальный кэш в статическом контексте, чтобы увидеть, есть ли уже созданный экземпляр... ну, ты меня поймал...

Это не enum usecase, потому что система будет динамически добавлять новые экземпляры валюты, рынка или даже обмена, которые все должны быть слабо связаны и созданы только один раз... (также для предотвращения тяжелых ГХ)

Итак, чтобы прояснить вопрос... подумайте о глобальной проблеме параллелизма, а не о конкретном примере.

Я нашел эту ссылку весьма полезно http://tutorials.jenkov.com/java-concurrency/read-write-locks.html

Я предполагаю, что в JDK уже есть некоторые типы блокировок для этой цели, но пока не уверен.

108   1  

1 ответ:

На самом деле я выступал по этому поводу только сегодня на конференции ФОСДЕМ в Бурсселе. Смотрите слайды здесь: http://www.slideshare.net/cruftex/cache2k-java-caching-turbo-charged-fosdem-2015

В основном вы можете использовать Google Guava, однако, поскольку Guava-это кэш, который использует LRU, все еще требуется синхронизированный блок. Что-то, что я исследую в cache2k, используется продвинутый алгоритм выселения, который не нуждается в манипуляциях со списком для доступа к кэшу, поэтому блокирует что-либо на все.

Cache2k находится на maven central, добавьте cache2k-api и cache2k-core в качестве зависимостей и инициализируйте кэш с помощью:

cache = 
  CacheBuilder.newCache(String.class, Object.class)
    .implementation(ClockProPlusCache.class)
    .build();

Если у вас есть только хиты кэша, cache2k примерно в 5 раз быстрее, чем Guava, и в 10 раз быстрее, чем EHCache. Для вашего шаблона использования, например, с типом валюты, вы можете запустить кэш в конфигурации чтения через и добавить источник кэша, который отвечает за построение экземпляров валюты.

Таким образом, вам не обязательно искать кэш. Для примера валюты кэш не нужен, так как существует ограниченное пространство экземпляров валюты. Если вы хотите сделать то же самое с возможным неограниченным пространством, кэш является более универсальным решением, поскольку вы должны ограничить потребление ресурсов. Один пример, который я исследовал, использует это для форматированных дат. Смотрите: https://github.com/headissue/cache2k-benchmark/blob/master/zoo/src/test/java/org/cache2k/benchmark/DateFormattingBenchmark.java

Для общих вопросов по cache2k, не стесняйтесь размещать их на переполнении стека.

    Ничего не найдено.

Добавить ответ:
Отменить.