Do you really use Map for caching in Java? Weak reference to WeakHashMap to understand

Do you really use Map for caching in Java? Weak reference to WeakHashMap to understand

Preface: When using Java Map for caching, have you considered the OOM problem caused by capacity and the impact of hit rate on performance? ?

In application system development, we often use third-party frameworks such as redis and memcache as caching solutions. Sometimes our requirements and application scenarios are not that complicated, and the delivery date is already in seconds. How dare we introduce third-party frameworks into existing applications, the fire burns the top of our heads bald. What to do at this time, performance, year-end bonus.

What should we consider about caching? -intsmaze

Maybe most people use caches only for fetching and storing operations, but yes! If you have an understanding of the computer operating system, you don't need to look at the configuration file of redis to know that the capacity should be considered. For example, the various FIFO and LRU algorithms of paging in the operating system are all for improving the hit rate. Similarly, we should consider the hit rate and capacity issues when using cache in applications. In particular, we should consider using Java's map for simple caching.

Goddess: Is the capacity? It’s so tall, don’t you just specify the capacity when you’re new, it’s that simple

new HashMap<Integer, Byte[]>(100);

intsmaze: Hello, you can try to add 101 elements to the map, and then traverse the map to see if the number of data traversed is 100 or 101. There is an array inside the HashMap, which will automatically expand.

Goddess: Oh, indeed. Then I will encapsulate the HashMap.

    private Map<String,String> map=new HashMap<String,String>();
    private int len;
    public intsmaze(int len)
    {
        this.len=len;
    }
    boolean put(String key,String value)
    {
        if(map.size()==len)
        {
            return false;
        }
        else
        {
            map.put(key, value);
            return true;
        }
    }

intsmaze: Hello, this does solve the OOM problem, but I don’t know if it’s improper to talk about it. If you do this, after putting len times, the subsequent data will not be stored, and you can always get it from Get the data len times, other data have to go to the hard disk to read?

Goddess: Yes, I set the size of len a bit larger, and then clear the value in the map every hour. Nothing is fine. Why are you targeting me?

intsmaze: Well, you can do this, but you have to spend time in the early stage of debugging the Map size, choose an appropriate size, and every hour, mysql and other storage will face a large number of requests, which is easy to cause a cache avalanche. And if performance is the most demanding, there is actually an improvement here. The hit rate determines the performance.

Goddess: What do you want? What is it?

intsmaze: At this time you can learn about FIFO, LRU, etc. If you have used redis, you should know, but you may know that redis has three strategies for hit rate (FIFO, LRU, LFU). So if we want to use Map as a cache, we should also consider the hit rate. I can't edit it later, so let's talk about the main point of this article.

WeakHashMap weak reference-intsmaze

WeakHashMap implements the Map interface and uses weak references as the storage solution for internal data. WeakHashMap is a typical application of weak references and can be used as a simple cache table solution. WeakHashMap will save all table items in the system memory range. Once the memory is not enough, the unreferenced table items will be quickly cleared during GC, thus avoiding system memory overflow. I won’t talk about weak references, Baidu has a lot of

        Map<Integer, Byte[]> map = null;

        map = new WeakHashMap<Integer, Byte[]>();
        for (int i = 0; i <10000; i++) {
            Integer integer = new Integer(i);
            map.put(integer, new Byte[i]);
        }
               //-Xmx5M found no OOM at this time

       //-Xmx5M java.lang.OutOfMemoryError: Java heap space
        map = new HashMap<Integer, Byte[]>(10);
        for (int i = 0; i <100; i++) {
            Integer integer = new Integer(i);
            map.put(integer, new Byte[i]);
        }

              //If the keys stored in WeakHashMap all have strong references, then WeakHashMap will degenerate into HashMap.
       //-Xmx5M java.lang.OutOfMemoryError: Java heap space
       //at cn.intsmaze.collection.MapCase.testWeakHash(MapCase.java:119)
        map = new WeakHashMap<Integer, Byte[]>();
        List list = new ArrayList();
        for (int i = 0; i <10000; i++) {
            Integer integer = new Integer(i);
            map.put(integer, new Byte[i]);//If you look down on me, you can comment this line, you will find that Jiang is still hot, and the memory overflow is caused by WeakHashMap instead of List.
            list.add(integer);
        }

If you want to automatically clean up data through WeakHashMap in the system, try not to force the WeakHashMap keys in other places in the system, otherwise, these keys will not be recycled, and WeakHashMap will not be able to release the entries they occupy normally.

Thread safety issues-intsmaze

As we know before, the use of WeakHashMap can ignore the capacity problem and increase the cache capacity. It's just that when the capacity is not enough, OOM will not occur, and internal data will be recovered by GC. There seems to be no way for the hit rate. Let me give a plan after losing a piece of hair in exchange for in-depth thinking. The use of WeakHashMap is generally a global variable, and there should be no application scenarios for local variables. Observing the source code of WeakHashMap, we can find that it is not thread-safe, so what should I do in a multi-threaded scenario?

Collections-intsmaze

WeakHashMap<String, String> weakHashMapintsmaze=new WeakHashMap<String, String>();
Map<String, String> intsmaze=Collections.synchronizedMap(weakHashMapintsmaze);

Just ask if you accept it.

ThreadLocal-intsmaze

A ThreadLocal records a weakHashMap. A good system does not constantly create and destroy threads, but has a thread pool for maintenance, so use ThreadLocal. If you don’t understand, you can follow me first, and then go