Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use JDK to implement your own cache

2025-04-02 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article introduces you how to use JDK to achieve their own cache, the content is very detailed, interested friends can refer to, hope to be helpful to you.

Demand analysis

This kind of scenario is often encountered in projects: a piece of data needs to be shared in multiple places, some of the data is timely, and expires automatically. For example, the verification code of a mobile phone needs to be cached after it is sent, and then for security reasons, it is generally necessary to set a period of validity, which expires automatically. How can we achieve such a function?

Solution

Use existing caching technology frameworks, such as redis,ehcache. Advantages: mature, stable, powerful; disadvantages, the project needs to introduce the corresponding framework, not light enough.

If you don't consider distribution and just cache data between single or multi-threads, you can actually write a caching tool by hand. Let's simply implement such a tool.

Code first:

Import java.util.HashMap; import java.util.Map; import java.util.concurrent.*; / * * @ Author: lixk * @ Date: 2018-5-9 15:03 * @ Description: simple memory caching utility class * / public class Cache {/ / collection of key-value pairs private final static Map map = new HashMap (); / / timer thread pool, used to clear expired cache private final static ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor () / * add cache * * @ param key key * @ param data value * / public synchronized static void put (String key, Object data) {Cache.put (key, data, 0) } / * add cache * * @ param key key * @ param data value * @ param expire expiration time (in milliseconds. 0 means * * long * / public synchronized static void put (String key, Object data, long expire) {/ / clear the original key value pair Cache.remove (key) / / set the expiration time if (expire > 0) {Future future = executor.schedule (new Runnable () {@ Override public void run () {/ / clear the key pair synchronized (Cache.class) {map.remove (key);}, expire, TimeUnit.MILLISECONDS); map.put (key, new Entity (data, future)) } else {/ / does not set expiration time map.put (key, new Entity (data, null));}} / * read cache * * @ param key key * @ return * / public synchronized static Object get (String key) {Entity entity = map.get (key); return entity = = null? Null: entity.getValue ();} / * * read cache * * @ param key key * * @ param clazz value type * @ return * / public synchronized static T get (String key, Class clazz) {return clazz.cast (Cache.get (key)) } / * clear cache * * @ param key * @ return * / public synchronized static Object remove (String key) {/ / clear original cache data Entity entity = map.remove (key); if (entity = = null) return null; / / clear original key value pair timer Future future = entity.getFuture (); if (future! = null) future.cancel (true); return entity.getValue () } / * query the number of key-value pairs currently cached * * @ return * / public synchronized static int size () {return map.size ();} / * cache entity class * / private static class Entity {/ / value private Object value; / / timer Future private Future future; public Entity (Object value, Future future) {this.value = value of key-value pairs This.future = future;} / * * get the value * * @ return * / public Object getValue () {return value;} / * get the Future object * * @ return * / public Future getFuture () {return future;}

This tool class is mainly implemented by HashMap+ timer thread pool, map is used to store key-value pair data, and map value is the internal class object of Cache Entity,Entity contains value and the life cycle timer Future of the key-value pair. Cache class only provides put (key, value), put (key, value, expire), get (key), get (key, class), remove (key), size () several synchronization methods.

When adding key-value pairs of data, the remove () method is first called to erase the original data of the same key, cancel the corresponding scheduled cleanup task, then add new data to the map, and, if the valid time is set, add the corresponding timed cleanup task to the timer thread pool.

test

Import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future / * * @ Author: lixk * @ Date: 2018-5-9 16:40 * @ Description: cache tool class test * / public class CacheTest {/ * test * * @ param args * / public static void main (String [] args) throws InterruptedException, ExecutionException {String key = "id" / / do not set expiration System.out.println ("* do not set expiration time *"); Cache.put (key, 123); System.out.println ("key:" + key + ", value:" + Cache.get (key)); System.out.println ("key:" + key + ", value:" + Cache.remove (key) System.out.println ("key:" + key + ", value:" + Cache.get (key)); / / set expiration time System.out.println ("* set expiration time *"); Cache.put (key, "123456", 1000); System.out.println ("key:" + key + ", value:" + Cache.get (key)); Thread.sleep (2000) " System.out.println ("key:" + key + ", value:" + Cache.get (key)); / * concurrent performance test * / System.out.println ("* concurrent performance test *") / / create a thread pool with 10 threads and add 1000000 operations to the thread pool ExecutorService executorService = Executors.newFixedThreadPool (10); Future [] futures = new Future [10]; / * add * / {long start = System.currentTimeMillis (); for (int j = 0; j)

< 10; j++) { futures[j] = executorService.submit(() ->

{for (int I = 0; I)

< 100000; i++) { Cache.put(Thread.currentThread().getId() + key + i, i, 300000); } }); } //等待全部线程执行完成,打印执行时间 for (Future future : futures) { future.get(); } System.out.printf("添加耗时:%dms ", System.currentTimeMillis() - start); } /********查询********/ { long start = System.currentTimeMillis(); for (int j = 0; j < 10; j++) { futures[j] = executorService.submit(() ->

{for (int I = 0; I < 1000000; iTunes +) {Cache.get (Thread.currentThread (). GetId () + key + I);}} / wait for all threads to complete, print execution time for (Future future: futures) {future.get ();} System.out.printf ("query time:% dms", System.currentTimeMillis ()-start) } System.out.println ("current cache capacity:" + Cache.size ());}}

Test results:

* do not set expiration time * key:id, value:123 key:id, value:123 key:id, value:null * set expiration time * key:id, value:123456 key:id Value:null * concurrent performance test * time to add: 2313ms query time: 335ms current cache capacity: 1000000

The test program uses a thread pool of 10 threads to simulate concurrency, performing a total of a million add and query operations in more than two seconds. 400000 read and write concurrency per second should still be able to meet most high concurrency scenarios ^ _ ^

On how to use JDK to achieve their own cache to share here, I hope the above content can be of some help to you, can learn more knowledge. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report