package cn.org.bjca.ywq.common.util.string; import com.google.common.cache.*; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** * <pre></pre> * * @文件名称: Main.java * @包 路 径: cn.org.bjca.ywq.common.util.string * @Copyright:北京数字医信责任有限公司 (C) 2022 * * @Description: * @Version: V1.0 * @Author: zhoujunmei * @Date:2022/4/11 16:51 * @Modify: */ public class Main { public static void main(String[] args) throws ExecutionException, InterruptedException{ //缓存接口这里是LoadingCache,LoadingCache在缓存项不存在时可以自动加载缓存 LoadingCache<String, Map<String,Boolean>> clientCache //CacheBuilder的构造函数是私有的,只能通过其静态方法newBuilder()来获得CacheBuilder的实例 = CacheBuilder.newBuilder() //设置并发级别为8,并发级别是指可以同时写缓存的线程数 // .concurrencyLevel(8) // .expireAfterAccess(8, TimeUnit.SECONDS) // //设置写缓存后8秒钟过期,设置后,当过期会自动执行load方法,但load方法执行完之前所有的获取缓存get方法会阻塞 .expireAfterWrite(8, TimeUnit.SECONDS) //设置缓存容器的初始容量为10 .initialCapacity(10) //设置缓存最大容量为100,超过100之后就会按照LRU最近虽少使用算法来移除缓存项 .maximumSize(100) //设置要统计缓存的命中率 .recordStats() //设置缓存的移除通知 .removalListener(new RemovalListener<Object, Object>() { @Override public void onRemoval(RemovalNotification<Object, Object> notification) { System.out.println(new Date() + " "+notification.getKey() + " was removed, cause is " + notification.getCause()); } }) //build方法中可以指定CacheLoader,在缓存不存在时通过CacheLoader的实现自动加载缓存 .build( new CacheLoader<String, Map<String,Boolean>>() { @Override public Map<String,Boolean> load(String key) throws Exception { System.out.println(new Date() +" load..start.." + key); Map<String,Boolean> clientMap = new HashMap<>(); int hour = Calendar.getInstance().get(Calendar.HOUR); int random = (int)(hour * Math.random()) + 1; for (int i=0;i<random;i++) { clientMap.put(i+"",true); } try { Thread.sleep(5000); } catch (Exception e) { } System.out.println(new Date() +" load..end.." + clientMap); return clientMap; } } ); //定时任务每隔N秒刷新缓存,refresh是异步的不会导致多线程并发load时导致阻塞,但再refresh期间执行load方法体期间,获取到的还是旧的缓存值 // ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(1); // scheduledExecutorService.scheduleAtFixedRate(new Runnable() { // @Override // public void run() { // clientCache.refresh("test"); // } // },0,10 ,TimeUnit.SECONDS); // 模拟3个线程进行缓存获取操作 Thread thread1= new Thread(new Runnable() { @Override public void run() { for (int i=0;i< 100;i++) { try { Map<String,Boolean> map = clientCache.get("test"); System.out.println(new Date() + Thread.currentThread().getName() + map); Thread.sleep(1000); } catch (Exception e) { } } } }); Thread thread2= new Thread(new Runnable() { @Override public void run() { for (int i=0;i< 100;i++) { try { Map<String,Boolean> map = clientCache.get("test"); System.out.println(new Date() + Thread.currentThread().getName() + map); Thread.sleep(1000); } catch (Exception e) { } } } }); Thread thread3= new Thread(new Runnable() { @Override public void run() { for (int i=0;i< 100;i++) { try { Map<String,Boolean> map = clientCache.get("test"); System.out.println(new Date() + Thread.currentThread().getName() + map); Thread.sleep(1000); } catch (Exception e) { } } } }); thread1.start(); thread2.start(); thread3.start(); //最后打印缓存的统计信息 命中率等 System.out.println(clientCache.stats().toString()); } }