Шукаєте простий кеш пам’яті Java [закритий]


102

Я шукаю простий кеш пам’яті Java, який має хорошу сумісність (тому LinkedHashMap недостатньо хороший), який можна періодично серіалізувати на диск.

Одна з особливостей, яка мені потрібна, але яку виявилося важко знайти, - це спосіб "заглянути" на об'єкт. Під цим я маю на увазі отримання об'єкта з кеша, не змушуючи кеш утримувати його довше, ніж це було б інакше.

Оновлення: Додатковою вимогою, яку я нехтував зазначити, є те, що мені потрібно мати змогу змінювати кешовані об’єкти (вони містять плаваючі масиви) на місці.

Чи може хтось надати якісь рекомендації?


1
Я шукаю щось подібне, що є "в процесі" та легшою вагою. Я хочу використовувати його для зберігання деяких даних у плагіні Eclipse у купі. Ehcache та JCS здаються надто важкими / розподіленими / J2EE на мій смак.
Урі


Я порекомендую Apache Ignite ( ignite.apache.org )
Bhagat S.

1
Що це питання закрите (через 6 років після факту), і це все ще щось, про що люди сьогодні задаються питанням, покаже, наскільки система модераторів SO не працює.
запилене

Відповіді:


61

Оскільки це питання було задано спочатку, бібліотека Google Guava тепер включає потужний і гнучкий кеш. Я б рекомендував використовувати це.


3
Зверніть увагу, що Spring вже не підтримує кеш-пам'ять Guava: stackoverflow.com/questions/44175085/…
грішник

@sanity це реалізує Jcache?
gaurav

Caffine також є приємною бібліотекою кешування. Кофеїн - це висока продуктивність, майже оптимальна бібліотека кешування на базі Java 8. Кофеїн забезпечує кеш пам’яті за допомогою API,
навіяного

37

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


2
Дякую, додаткове запитання: Якщо я отримаю об’єкт з EHcache (скажімо, масив), і зміню його - чи буде об’єкт оновлений у кеші? тобто. чи підтримує EHCache посилання на об'єкти?
санітарність

1
Я вважаю так, але щоб це зробити безпечно, ви, звичайно, повинні відповідним чином зафіксувати об'єкт.
Алекс Міллер

Я люблю ehcache, однак, це баночка 10mb. Шлях занадто великий.
marthegrea

23

Якщо вам потрібно щось просте, чи відповідає це законопроекту?

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

Це не зберегти на диску, але ви сказали, що хочете просто ...

Посилання:

(Як зауважив Адам, синхронізація карти вражає ефективністю. Не кажучи, що ідея не має на ній волосся, але це буде досить швидким і брудним рішенням.)


4
Синхронізація цілої гігантської карти - це здоровенне покарання. Ви можете легко зберігати слабкі типи у паралельній карті хешу та періодично їх видаляти.
Адам Гент

7
ConcurrentHashMap краще, ніж Collections.synchronizedMap stackoverflow.com/questions/6692008/…
Пабло Моретті

8
ConcurrentHashMap абсолютно ефективний, але він не має властивостей WeakHashMap з огляду на те, що дозволяє сміттєзбірникам відновлювати пам'ять. Це для вас може бути або не бути важливим.
Еван

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, якщо я закрию свою програму, кеш знищить усі зареєстровані дані чи ні?
Менай Ала Еддін - Аладдін

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

Чи можу я порекомендувати використовувати enum для одиночного? dzone.com/articles/java-singletons-using-enum
Ерк

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



0

Спробуйте Ehcache ? Це дозволяє вам підключити власні алгоритми закінчення терміну дії, щоб ви могли контролювати свою функціональність.

Ви можете серіалізувати на диск, базу даних, через кластер тощо ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.