Ищете простой кеш в памяти Java [закрыто]

102

Я ищу простой Java-кеш в памяти, который имеет хороший параллелизм (поэтому LinkedHashMap недостаточно хорош) и который можно периодически сериализовать на диск.

Одна функция, которая мне нужна, но которую оказалось трудно найти, - это способ «взглянуть» на объект. Под этим я подразумеваю получение объекта из кеша, не заставляя кеш удерживать объект дольше, чем в противном случае.

Обновление: дополнительное требование, о котором я забыл упомянуть, заключается в том, что мне нужно иметь возможность изменять кэшированные объекты (они содержат массивы с плавающей запятой) на месте.

Кто-нибудь может дать какие-либо рекомендации?

здравомыслие
источник
1
Я ищу что-то похожее, что «в процессе» и более легкое. Я хочу использовать его для хранения некоторых данных в плагине Eclipse в куче. Ehcache и JCS кажутся мне слишком тяжелыми / распределенными / J2EE.
Uri
1
возможный дубликат API облегченного кеширования объектов Java
Raedwald
Я буду рекомендовать Apache Ignite ( ignite.apache.org )
Бхагат С.
1
То, что этот вопрос закрыт (через 6 лет после факта), и люди все еще задаются вопросом сегодня, покажите, как система модераторов SO дает сбой.
dustinevan

Ответы:

62

Поскольку этот вопрос был задан изначально, библиотека Google Guava теперь включает мощный и гибкий кеш. Я бы рекомендовал использовать это.

здравомыслие
источник
3
Пожалуйста , обратите внимание , что весна не поддерживает кэш Guava больше: stackoverflow.com/questions/44175085/...
грешник
@sanity реализует ли он Jcache?
Gaurav
Caffine также является хорошей и производительной библиотекой кеширования. Caffeine - это высокопроизводительная, почти оптимальная библиотека кеширования на основе Java 8. Caffeine обеспечивает кеширование в памяти с использованием API, вдохновленного Google Guava
Slavus
38

Ehcache - довольно хорошее решение для этого и имеет способ заглянуть ( метод getQuiet () ), чтобы он не обновлял временную метку простоя. Внутри Ehcache реализован с помощью набора карт, вроде ConcurrentHashMap, поэтому он имеет аналогичные преимущества параллелизма.

Алекс Миллер
источник
2
Спасибо, дополнительный вопрос: если я получу объект из EHcache (скажем, массив) и изменю его - будет ли объект обновлен в кеше? т.е. поддерживает ли EHCache ссылки на объекты?
здравомыслие,
1
Я так считаю, но для того, чтобы сделать это безопасно, вы, конечно, должны соответствующим образом заблокировать объект.
Alex Miller
Я люблю ehcache, но это баночка размером 10 МБ. Слишком большой.
markthegrea
24

Если вам нужно что-то простое, будет ли это отвечать всем требованиям?

Map<K, V> myCache = Collections.synchronizedMap(new WeakHashMap<K, V>());

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

Ссылки:

(Как прокомментировал Адам, синхронизация карты снижает производительность. Не говоря уже о том, что у этой идеи нет проблем, но было бы достаточно быстрого и грязного решения.)

Эван
источник
4
Синхронизация всей гигантской карты - это серьезное наказание. Вы можете легко сохранить слабые типы в параллельной хэш-карте и периодически удалять их.
Адам Гент
7
ConcurrentHashMap лучше, чем Collections.synchronizedMap stackoverflow.com/questions/6692008/…
Пабло Моретти
8
С точки зрения производительности ConcurrentHashMap работает абсолютно лучше, но он не разделяет свойства WeakHashMap в отношении разрешения сборщику мусора освобождать память. Это может быть важно для вас, а может и нет.
Evan
4
Тогда используйте ConcurrentHashMap<WeakReference<T>>. docs.oracle.com/javase/7/docs/api/java/lang/ref/…
jdmichal
19

Другой вариант для java-кеша в памяти - cache2k . Производительность в памяти превосходит EHCache и google guava, см. Страницу тестов cache2k .

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

Cache<String,String> cache = new Cache2kBuilder<String, String>() {}
  .expireAfterWrite(5, TimeUnit.MINUTES)    // expire/refresh after 5 minutes
  .resilienceDuration(30, TimeUnit.SECONDS) // cope with at most 30 seconds
                                          // outage before propagating 
                                          // exceptions
  .refreshAhead(true)                       // keep fresh when expiring
  .loader(new CacheLoader<String, String>() {
    @Override
    public String load(final String key) throws Exception {
      return ....;
    }
  })
  .build();
String val = cache.peek("something");
cache.put("something", "hello");
val = cache.get("something");

Если у вас есть зависимость от google guava, хорошей альтернативой может быть проверка кеша guava.

Cruftex
источник
cruftex, если я закрою свое приложение, кеш уничтожит все зарегистрированные данные или нет?
Менай Ала Эддин - Аладдин
10

Вы можете легко использовать imcache . Пример кода ниже.

void example(){
    Cache<Integer,Integer> cache = CacheBuilder.heapCache().
    cacheLoader(new CacheLoader<Integer, Integer>() {
        public Integer load(Integer key) {
            return null;
        }
    }).capacity(10000).build(); 
}
Юсуфайтас
источник
9

Попробуй это:

import java.util.*;

public class SimpleCacheManager {

    private static SimpleCacheManager instance;
    private static Object monitor = new Object();
    private Map<String, Object> cache = Collections.synchronizedMap(new HashMap<String, Object>());

    private SimpleCacheManager() {
    }

    public void put(String cacheKey, Object value) {
        cache.put(cacheKey, value);
    }

    public Object get(String cacheKey) {
        return cache.get(cacheKey);
    }

    public void clear(String cacheKey) {
        cache.put(cacheKey, null);
    }

    public void clear() {
        cache.clear();
    }

    public static SimpleCacheManager getInstance() {
        if (instance == null) {
            synchronized (monitor) {
                if (instance == null) {
                    instance = new SimpleCacheManager();
                }
            }
        }
        return instance;
    }

}
Сергей Богуцкий
источник
Проблемы с использованием синхронизированной карты уже обсуждались в других ответах.
вменяемость
@sergeyB: Я искал аналогичное решение, простое для реализации кеша ... Спасибо
Prakruti Pathik
1
public static SimpleCacheManager getInstance() {должно быть public synchronized static SimpleCacheManager getInstance() {иначе if (instance == null) {не является потокобезопасным. В этом случае вы можете удалить объект монитора все вместе, поскольку синхронизация выполняется для всех вызовов getInstance (), см .: javaworld.com/article/2073352/core-java/…
Can Kavaklıoğlu
Могу я порекомендовать использовать перечисление для синглтона? dzone.com/articles/java-singletons-using-enum
Erk,
9

Попробуйте @Cacheableиз jcabi-аспектов . С помощью одной аннотации вы делаете весь результат метода кешируемым в памяти:

public class Resource {
  @Cacheable(lifetime = 5, unit = TimeUnit.SECONDS)
  public String load(URL url) {
    return url.openConnection().getContent();
  }
}

Также прочтите эту статью: http://www.yegor256.com/2014/08/03/cacheable-java-annotation.html

Егор256
источник
3

Как насчет этого: https://commons.apache.org/proper/commons-jcs/ (обновлено на новый адрес, поскольку JCS теперь находится в Apache Commons)

Тофу пиво
источник
Похоже, @sanity хотел световой кеш.
Родольфо
0

Попробуйте Ehcache ? Он позволяет вам подключать собственные алгоритмы истечения срока действия кеширования, чтобы вы могли контролировать свои функции просмотра.

Вы можете сериализовать на диск, в базу данных, в кластере и т. Д.

Стивен
источник