「java设置缓存参数」java如何实现缓存技术

博主:adminadmin 2023-03-20 21:19:09 311

本篇文章给大家谈谈java设置缓存参数,以及java如何实现缓存技术对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。

本文目录一览:

java内存或者是缓存管理怎么实现?

晕, 你确定你是用Java,

OK,不管Java还是C#

1. 定义你的map

HashMapString, String map = new HashMapString, String();

2. 存入你的信息, 反正你得要有个唯一标识的key,以及你想存的对象

map.put("userid", "userMessage");

....

3. 每次存入后,判断一下当前大小,java 的hashmap是size()方法,如果大于你的最大数,把原来存的前进前出删掉

if(map.size()100){

//map.remove(arg0)

....

}

更高级内容:

如果对map中的cache内容有过访问,给该内容的权重+1,每次删除的时候先将权重由小至大删除。 这就是命中率缓存,一般缓存都是按这种算法做的,只是具体算法有改进

JVM常用参数

-Xmx4g 初始堆大小 4g

-Xms4g 最大堆大小4g

-Xmn512m 年轻代大小(1.4or lator)整个JVM内存大小=年轻代大小 + 年老代大小 + 持久代大小。持久代一般固定大小为64m,所以增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8

-XX:MetaspaceSize=256m 设置元空间初始大小为256m

-XX:MaxMetaspaceSize=512m 设置元空间最大可分配大小512m

-Xss256k 每个线程的堆栈大小256k

-XX:+ExplicitGCInvokesConcurrent 降低每次Full GC的时间,其实就是启用多线程去执行

-XX:+UseConcMarkSweepGC 启用CMS做为垃圾收集

-XX:+UseCMSInitiatingOccupancyOnly 只有开启了这个参数,CMSInitiatingOccupancyFraction这个参数才会生效

-XX:CMSInitiatingOccupancyFraction=70 CMS垃圾收集器,当老年代达到70%时,触发CMS垃圾回收。

-XX:ParallelGCThreads=4 选项指定在默认垃圾收集器的并行操作期间使用的线程数为4

-XX:-UseBiasedLocking 关闭用户偏向锁

-XX:AutoBoxCacheMax=20000 参数是设置Integer缓存上限的参数,在VM初始化期间java.lang.Integer.IntegerCache.high属性可以被设置和保存在私有的系统属性sun.misc.VM class中。理论上讲,当系统需要频繁使用Integer时,或者说堆内存中存在大量的Integer对象时,可以考虑提高Integer缓存上限,避免JVM重复创造对象,提高内存的使用率,减少GC的频率,从而提高系统的性能。

-XX:MaxTenuringThreshold=6 设置的是年龄阈值,默认15(对象被复制的次数),这里设置成了6次

-XX:+PrintGCApplicationStoppedTime 打印垃圾收集时 , 系统的停顿时间

-XX:+PrintGCDateStamps 打印CG发生的时间戳

-XX:+PrintGCDetails 来打印详细的GC日志来查看

-XX:+PrintCodeCache 会打印Code Cache区的使用情况。

-Xloggc:/dev/shm/gc.log 指定gc的log日志所在位置/dev/shm/gc.log

-XX:+UseGCLogFileRotation 打开或关闭GC日志滚动记录功能,要求必须设置 -Xloggc参数

-XX:NumberOfGCLogFiles=2 设置滚动日志文件的个数,必须大于1

日志文件命名策略是,filename.0, filename.1, ..., filename.n-1,其中n是该参数的值

-XX:GCLogFileSize=10m 设置滚动日志文件的大小,必须大于8k

当前写日志文件大小超过该参数值时,日志将写入下一个文件

-XX:+HeapDumpOnOutOfMemoryError 表示当JVM发生OOM时,自动生成DUMP文件。

-XX:HeapDumpPath=/root/logs/ 发生了 内存溢出错误 dump路径为root/logs/ (一般与HeapDumpOnOutOfMemoryError参数一块使用)

skywalking agent 本地缓存队列参数设置

skywalking是一款优秀的apm应用性能监控软件,属于Apache开源平台顶级项目,以java语言开发。它以jvm虚拟机agent方式随应用一块启动,通过无侵入自动代码埋点来实现应用接口的性能监控。

由于agent代理和监控的业务应用在一块启动,为尽可能地减小对原有业务应用的影响(内存占用、线程cpu资源使用等),skywalking agent的埋点数据收集以及上报,是以队列+异步线程的方式实现。当skywalking server端出现故障,内存队列被占满,新的收集数据将直接丢弃,不会继续往队列里添加,以避免占用过多内存资源对原有业务产生影响。通常情况下,保持agent默认参数配置即可,无需额外修改。针对一些需求特别的场景,用户可以通过参数自行定义,以便最大限度降低agent对原有业务的影响。

关于skywalking agent的队列模型-- 无锁环状队列。可以参考文章:,这里不再赘述。

skywalking agent本地缓存队列由两部分组成: 缓存通道*通道队列

其中,

缓存通道大小:buffer.channel_size=${SW_BUFFER_CHANNEL_SIZE:5}

缓存队列大小:buffer.buffer_size=${SW_BUFFER_BUFFER_SIZE:300}

上面所列参数,等号左侧为k ey值,右侧为value值,其中value值中大写字符为环境变量,冒号:后面数字为默认值。即agent的默认缓存通道为5,默认每个通道对应队列大小为300。

我们可以通过以下两种方式实现默认参数的覆盖。

java修改 方法 缓存没

缓存是在web开发中经常用到的,将程序经常使用到或调用到的对象存在内存中,或者是耗时较长但又不具有实时性的查询数据放入内存中,在一定程度上可以提高性能和效率。下面我实现了一个简单的缓存,步骤如下。

创建缓存对象EntityCache.java

?

123456789101112131415161718192021222324252627282930313233343536373839404142

public class EntityCache { /** * 保存的数据 */ private Object datas; /** * 设置数据失效时间,为0表示永不失效 */ private long timeOut; /** * 最后刷新时间 */ private long lastRefeshTime; public EntityCache(Object datas, long timeOut, long lastRefeshTime) { this.datas = datas; this.timeOut = timeOut; this.lastRefeshTime = lastRefeshTime; } public Object getDatas() { return datas; } public void setDatas(Object datas) { this.datas = datas; } public long getTimeOut() { return timeOut; } public void setTimeOut(long timeOut) { this.timeOut = timeOut; } public long getLastRefeshTime() { return lastRefeshTime; } public void setLastRefeshTime(long lastRefeshTime) { this.lastRefeshTime = lastRefeshTime; } }

定义缓存操作接口,ICacheManager.java

?

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667

public interface ICacheManager { /** * 存入缓存 * @param key * @param cache */ void putCache(String key, EntityCache cache); /** * 存入缓存 * @param key * @param cache */ void putCache(String key, Object datas, long timeOut); /** * 获取对应缓存 * @param key * @return */ EntityCache getCacheByKey(String key); /** * 获取对应缓存 * @param key * @return */ Object getCacheDataByKey(String key); /** * 获取所有缓存 * @param key * @return */ MapString, EntityCache getCacheAll(); /** * 判断是否在缓存中 * @param key * @return */ boolean isContains(String key); /** * 清除所有缓存 */ void clearAll(); /** * 清除对应缓存 * @param key */ void clearByKey(String key); /** * 缓存是否超时失效 * @param key * @return */ boolean isTimeOut(String key); /** * 获取所有key * @return */ SetString getAllKeys();}

实现接口ICacheManager,CacheManagerImpl.java

这里我使用了ConcurrentHashMap来保存缓存,本来以为这样就是线程安全的,其实不然,在后面的测试中会发现它并不是线程安全的。

?

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107

public class CacheManagerImpl implements ICacheManager { private static MapString, EntityCache caches = new ConcurrentHashMapString, EntityCache(); /** * 存入缓存 * @param key * @param cache */ public void putCache(String key, EntityCache cache) { caches.put(key, cache); } /** * 存入缓存 * @param key * @param cache */ public void putCache(String key, Object datas, long timeOut) { timeOut = timeOut 0 ? timeOut : 0L; putCache(key, new EntityCache(datas, timeOut, System.currentTimeMillis())); } /** * 获取对应缓存 * @param key * @return */ public EntityCache getCacheByKey(String key) { if (this.isContains(key)) { return caches.get(key); } return null; } /** * 获取对应缓存 * @param key * @return */ public Object getCacheDataByKey(String key) { if (this.isContains(key)) { return caches.get(key).getDatas(); } return null; } /** * 获取所有缓存 * @param key * @return */ public MapString, EntityCache getCacheAll() { return caches; } /** * 判断是否在缓存中 * @param key * @return */ public boolean isContains(String key) { return caches.containsKey(key); } /** * 清除所有缓存 */ public void clearAll() { caches.clear(); } /** * 清除对应缓存 * @param key */ public void clearByKey(String key) { if (this.isContains(key)) { caches.remove(key); } } /** * 缓存是否超时失效 * @param key * @return */ public boolean isTimeOut(String key) { if (!caches.containsKey(key)) { return true; } EntityCache cache = caches.get(key); long timeOut = cache.getTimeOut(); long lastRefreshTime = cache.getLastRefeshTime(); if (timeOut == 0 || System.currentTimeMillis() - lastRefreshTime = timeOut) { return true; } return false; } /** * 获取所有key * @return */ public SetString getAllKeys() { return caches.keySet(); }}

CacheListener.java,监听失效数据并移除。

?

1234567891011121314151617181920212223

public class CacheListener{ Logger logger = Logger.getLogger("cacheLog"); private CacheManagerImpl cacheManagerImpl; public CacheListener(CacheManagerImpl cacheManagerImpl) { this.cacheManagerImpl = cacheManagerImpl; } public void startListen() { new Thread(){ public void run() { while (true) { for(String key : cacheManagerImpl.getAllKeys()) { if (cacheManagerImpl.isTimeOut(key)) { cacheManagerImpl.clearByKey(key); logger.info(key + "缓存被清除"); } } } } }.start(); }}

测试类TestCache.java

?

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556

public class TestCache { Logger logger = Logger.getLogger("cacheLog"); /** * 测试缓存和缓存失效 */ @Test public void testCacheManager() { CacheManagerImpl cacheManagerImpl = new CacheManagerImpl(); cacheManagerImpl.putCache("test", "test", 10 * 1000L); cacheManagerImpl.putCache("myTest", "myTest", 15 * 1000L); CacheListener cacheListener = new CacheListener(cacheManagerImpl); cacheListener.startListen(); logger.info("test:" + cacheManagerImpl.getCacheByKey("test").getDatas()); logger.info("myTest:" + cacheManagerImpl.getCacheByKey("myTest").getDatas()); try { TimeUnit.SECONDS.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } logger.info("test:" + cacheManagerImpl.getCacheByKey("test")); logger.info("myTest:" + cacheManagerImpl.getCacheByKey("myTest")); } /** * 测试线程安全 */ @Test public void testThredSafe() { final String key = "thread"; final CacheManagerImpl cacheManagerImpl = new CacheManagerImpl(); ExecutorService exec = Executors.newCachedThreadPool(); for (int i = 0; i 100; i++) { exec.execute(new Runnable() { public void run() { if (!cacheManagerImpl.isContains(key)) { cacheManagerImpl.putCache(key, 1, 0); } else { //因为+1和赋值操作不是原子性的,所以把它用synchronize块包起来 synchronized (cacheManagerImpl) { int value = (Integer) cacheManagerImpl.getCacheDataByKey(key) + 1; cacheManagerImpl.putCache(key,value , 0); } } } }); } exec.shutdown(); try { exec.awaitTermination(1, TimeUnit.DAYS); } catch (InterruptedException e1) { e1.printStackTrace(); } logger.info(cacheManagerImpl.getCacheDataByKey(key).toString()); }}

testCacheManager()输出结果如下:

?

123456789101112

2017-4-17 10:33:51 io.github.brightloong.cache.TestCache testCacheManager信息: test:test2017-4-17 10:33:51 io.github.brightloong.cache.TestCache testCacheManager信息: myTest:myTest2017-4-17 10:34:01 io.github.brightloong.cache.CacheListener$1 run信息: test缓存被清除2017-4-17 10:34:06 io.github.brightloong.cache.CacheListener$1 run信息: myTest缓存被清除2017-4-17 10:34:11 io.github.brightloong.cache.TestCache testCacheManager信息: test:null2017-4-17 10:34:11 io.github.brightloong.cache.TestCache testCacheManager信息: myTest:null

testThredSafe()输出结果如下(选出了各种结果中的一个举例):

?

12

2017-4-17 10:35:36 io.github.brightloong.cache.TestCache testThredSafe信息: 96

可以看到并不是预期的结果100,为什么呢?ConcurrentHashMap只能保证单次操作的原子性,但是当复合使用的时候,没办法保证复合操作的原子性,以下代码:

?

123

if (!cacheManagerImpl.isContains(key)) { cacheManagerImpl.putCache(key, 1, 0); }

多线程的时候回重复更新value,设置为1,所以出现结果不是预期的100。所以办法就是在CacheManagerImpl.java中都加上synchronized,但是这样一来相当于操作都是串行,使用ConcurrentHashMap也没有什么意义,不过只是简单的缓存还是可以的。或者对测试方法中的run里面加上synchronized块也行,都是大同小异。

关于java设置缓存参数和java如何实现缓存技术的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。