Java foundation of the expiration time can be set map

Java foundation of the expiration time can be set map

First, the technical background

In the actual project development, we often use to cache middleware (such as redis, MemCache, etc.) to help us improve the usability and robustness of the system.

But many times if the project is relatively simple, there is no need to use specially introduced Redis caching middleware and so on to increase the complexity of the system. So Java itself has a lightweight component does not cache it easy to use.

The answer of course is there myself, but also more than one way. Common solution has: ExpiringMap, LoadingCache HashMap-based package and three.

Second, the technical effect

  • Implement caching of common functions, such as deleting outdated policy
  • Preheat hot data

Three, ExpiringMap

3.1 Introduction

  1. Map of Entry can be set to automatically expire after a certain period of time.
  2. Map may be provided to accommodate the maximum value, after reaching the Maximum size, reinserted value results in a value of the Map expired.
  3. Be added to monitor events scheduled listening function when listening to Entry expired.
  4. You can set lazy loading, creating an object when calling the get () method.

3.2 Source

github address

3.3 Example

  1. Add dependent (Maven)
<dependency> 
    <groupId>net.jodah</groupId> 
    <artifactId>expiringmap</artifactId> 
    <version>0.5.8</version> 
</dependency> 
  1. Example Source
public class ExpiringMapApp {

	public static void main(String[] args) {
		// maxSize: 设置最大值,添加第11个entry时,会导致第1个立马过期(即使没到过期时间)
		// expiration:设置每个key有效时间10s, 如果key不设置过期时间,key永久有效。
		// variableExpiration: 允许更新过期时间值,如果不设置variableExpiration,不允许后面更改过期时间,一旦执行更改过期时间操作会抛异常UnsupportedOperationException
		// policy:
		//        CREATED: 只在put和replace方法清零过期时间
		//        ACCESSED: 在CREATED策略基础上增加, 在还没过期时get方法清零过期时间。
		//        清零过期时间也就是重置过期时间,重新计算过期时间.
		ExpiringMap<String, String> map = ExpiringMap.builder()
			.maxSize(10)
			.expiration(10, TimeUnit.SECONDS)
			.variableExpiration().expirationPolicy(ExpirationPolicy.CREATED).build();

		map.put("token", "lkj2412lj1412412nmlkjl2n34l23n4");
		map.put("name", "管理员", 20000, TimeUnit.SECONDS);

		// 模拟线程等待...
		try {
			Thread.sleep(15000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("token ===> " + map.get("token"));
		System.out.println("name ===> " + map.get("name"));

		// 注意: 在创建map时,指定的那些参数如过期时间和过期策略都是全局的, 对map中添加的每一个entry都适用.
		//        在put一个entry键值对时可以对当前entry 单独设置 过期时间、过期策略,只对当前这个entry有效.
	}
}

operation result

token ===> null
name ===> 管理员
  1. note
  • When you create a map, such as those parameters specified expiration time and expiration policies are global, each entry is added to the map are applicable.
  • When put to a key entry on the current entry can be set individually expiration time, the expiration policy, this is only valid for the current entry.

四、LoadingCache

4.1 Introduction

Google open source out of a thread-safe local caching solution.

Features: Provides caching recovery mechanism to monitor the cache loader / hit, the flexible and powerful features, easy approachable api.

4.2 Example

  1. Source
public class LoadingCacheApp {

	public static void main(String[] args) throws Exception {
		// maximumSize: 缓存池大小,在缓存项接近该大小时, Guava开始回收旧的缓存项
		// expireAfterAccess: 设置时间对象没有被读/写访问则对象从内存中删除(在另外的线程里面不定期维护)
		// removalListener: 移除监听器,缓存项被移除时会触发的钩子
		// recordStats: 开启Guava Cache的统计功能
		LoadingCache<String, String> cache = CacheBuilder.newBuilder()
			.maximumSize(100)
			.expireAfterAccess(10, TimeUnit.SECONDS)
			.removalListener(new RemovalListener<String, String>() {
				@Override
				public void onRemoval(RemovalNotification<String, String> removalNotification) {
					System.out.println("过时删除的钩子触发了... key ===> " + removalNotification.getKey());
				}
			})
			.recordStats()
			.build(new CacheLoader<String, String>() {
				// 处理缓存键不存在缓存值时的处理逻辑
				@Override
				public String load(String key) throws Exception {
					return "不存在的key";
				}
			});

		cache.put("name", "小明");
		cache.put("pwd", "112345");

		// 模拟线程等待...
		try {
			Thread.sleep(15000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("token ===> " + cache.get("name"));
		System.out.println("name ===> " + cache.get("pwd"));
	}
}
  1. operation result
过时删除的钩子触发了... key ===> name
token ===> 不存在的key
过时删除的钩子触发了... key ===> pwd
name ===> 不存在的key

Removing mechanism 4.3

remove guava do when data cache is divided into passive removing and active removal of two kinds.

Passive removed

  • Based on the size of the removed: the number reaches the specified size, it will not commonly used keys removed
  • expireAfterAccess (long, TimeUnit) after removal of the amount of time since the last visit according to a key: based on the removal of time. expireAfterWrite (long, TimeUnit) removed on how much time after being created or a value to be replaced according to a key
  • Remove the reference-based: mainly based on java garbage collection, according to the reference value of the relationship between the key or decide to remove

Take the initiative to remove

  • Alone removed: Cache.invalidate (key)
  • Batch removed: Cache.invalidateAll (keys)
  • Remove all: Cache.invalidateAll ()

If the listener is removed configuration RemovalListener, the synchronization will be performed when all the actions to remove listenerthe logic under.

For asynchronous changed, use: RemovalListeners.asynchronous(RemovalListener, Executor).

4.4 Other

  • Before put in operation, if you already have the key, will first trigger removalListener remove the listener, add
  • Configuring the expireAfterAccess and expireAfterWrite, but has not been removed after a specified time.
  • Delete policy logic:

CacheBuilder build cache does not automatically run at a specific time to clean up and recovery work, will not immediately clean up after a cache entry expires, it will not start a thread to perform cache maintenance, because the first thread is relatively heavy, followed by some environmental constraints created thread.

Incidentally, it will do a small amount of maintenance work on a write, or do occasionally read operation. Of course, you can also create your own maintenance thread, at fixed time intervals to call Cache.cleanUp ().

Five, HashMap package

We can refer to the above two ideas Toolkit, a package can set their own outdated HashMap time to achieve the effect we want.

Published 164 original articles · won praise 166 · views 290 000 +

Guess you like

Origin blog.csdn.net/weixin_39723544/article/details/104527249