Looly 5 年 前
コミット
4cc276e665

+ 1 - 0
CHANGELOG.md

@@ -14,6 +14,7 @@
 * 【core   】     xml.setXmlStandalone(true)格式优化(pr#1234@Github)
 * 【core   】     xml.setXmlStandalone(true)格式优化(pr#1234@Github)
 * 【core   】     AnnotationUtil增加setValue方法(pr#1250@Github)
 * 【core   】     AnnotationUtil增加setValue方法(pr#1250@Github)
 * 【core   】     ZipUtil增加get方法
 * 【core   】     ZipUtil增加get方法
+* 【cache  】     对CacheObj等变量使用volatile关键字
 
 
 ### Bug修复
 ### Bug修复
 * 【cron   】     修复CronTimer可能死循环的问题(issue#1224@Github)
 * 【cron   】     修复CronTimer可能死循环的问题(issue#1224@Github)

+ 11 - 10
hutool-cache/src/main/java/cn/hutool/cache/impl/AbstractCache.java

@@ -6,6 +6,7 @@ import cn.hutool.core.lang.func.Func0;
 
 
 import java.util.Iterator;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.StampedLock;
 import java.util.concurrent.locks.StampedLock;
 
 
 /**
 /**
@@ -44,11 +45,11 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
 	/**
 	/**
 	 * 命中数
 	 * 命中数
 	 */
 	 */
-	protected int hitCount;
+	protected AtomicLong hitCount;
 	/**
 	/**
 	 * 丢失数
 	 * 丢失数
 	 */
 	 */
-	protected int missCount;
+	protected AtomicLong missCount;
 
 
 	// ---------------------------------------------------------------- put start
 	// ---------------------------------------------------------------- put start
 	@Override
 	@Override
@@ -113,15 +114,15 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
 	/**
 	/**
 	 * @return 命中数
 	 * @return 命中数
 	 */
 	 */
-	public int getHitCount() {
-		return hitCount;
+	public long getHitCount() {
+		return hitCount.get();
 	}
 	}
 
 
 	/**
 	/**
 	 * @return 丢失数
 	 * @return 丢失数
 	 */
 	 */
-	public int getMissCount() {
-		return missCount;
+	public long getMissCount() {
+		return missCount.get();
 	}
 	}
 
 
 	@Override
 	@Override
@@ -157,15 +158,15 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
 			// 不存在或已移除
 			// 不存在或已移除
 			final CacheObj<K, V> co = cacheMap.get(key);
 			final CacheObj<K, V> co = cacheMap.get(key);
 			if (null == co) {
 			if (null == co) {
-				missCount++;
+				missCount.getAndIncrement();
 				return null;
 				return null;
 			}
 			}
 
 
 			if (co.isExpired()) {
 			if (co.isExpired()) {
-				missCount++;
+				missCount.getAndIncrement();
 			} else{
 			} else{
 				// 命中
 				// 命中
-				hitCount++;
+				hitCount.getAndIncrement();
 				return co.get(isUpdateLastAccess);
 				return co.get(isUpdateLastAccess);
 			}
 			}
 		} finally {
 		} finally {
@@ -318,7 +319,7 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
 		final CacheObj<K, V> co = cacheMap.remove(key);
 		final CacheObj<K, V> co = cacheMap.remove(key);
 		if (withMissCount) {
 		if (withMissCount) {
 			// 在丢失计数有效的情况下,移除一般为get时的超时操作,此处应该丢失数+1
 			// 在丢失计数有效的情况下,移除一般为get时的超时操作,此处应该丢失数+1
-			this.missCount++;
+			this.missCount.getAndIncrement();
 		}
 		}
 		return co;
 		return co;
 	}
 	}

+ 4 - 3
hutool-cache/src/main/java/cn/hutool/cache/impl/CacheObj.java

@@ -1,6 +1,7 @@
 package cn.hutool.cache.impl;
 package cn.hutool.cache.impl;
 
 
 import java.io.Serializable;
 import java.io.Serializable;
+import java.util.concurrent.atomic.AtomicLong;
 
 
 /**
 /**
  * 缓存对象
  * 缓存对象
@@ -16,9 +17,9 @@ public class CacheObj<K, V> implements Serializable{
 	protected final V obj;
 	protected final V obj;
 	
 	
 	/** 上次访问时间 */
 	/** 上次访问时间 */
-	private long lastAccess; 
+	private volatile long lastAccess;
 	/** 访问次数 */
 	/** 访问次数 */
-	protected long accessCount;
+	protected AtomicLong accessCount;
 	/** 对象存活时长,0表示永久存活*/
 	/** 对象存活时长,0表示永久存活*/
 	private final long ttl;
 	private final long ttl;
 	
 	
@@ -61,7 +62,7 @@ public class CacheObj<K, V> implements Serializable{
 		if(isUpdateLastAccess) {
 		if(isUpdateLastAccess) {
 			lastAccess = System.currentTimeMillis();
 			lastAccess = System.currentTimeMillis();
 		}
 		}
-		accessCount++;
+		accessCount.getAndIncrement();
 		return this.obj;
 		return this.obj;
 	}
 	}
 	
 	

+ 3 - 4
hutool-cache/src/main/java/cn/hutool/cache/impl/LFUCache.java

@@ -69,21 +69,20 @@ public class LFUCache<K, V> extends AbstractCache<K, V> {
 			}
 			}
 
 
 			//找出访问最少的对象
 			//找出访问最少的对象
-			if (comin == null || co.accessCount < comin.accessCount) {
+			if (comin == null || co.accessCount.get() < comin.accessCount.get()) {
 				comin = co;
 				comin = co;
 			}
 			}
 		}
 		}
 
 
 		// 减少所有对象访问量,并清除减少后为0的访问对象
 		// 减少所有对象访问量,并清除减少后为0的访问对象
 		if (isFull() && comin != null) {
 		if (isFull() && comin != null) {
-			long minAccessCount = comin.accessCount;
+			long minAccessCount = comin.accessCount.get();
 
 
 			values = cacheMap.values().iterator();
 			values = cacheMap.values().iterator();
 			CacheObj<K, V> co1;
 			CacheObj<K, V> co1;
 			while (values.hasNext()) {
 			while (values.hasNext()) {
 				co1 = values.next();
 				co1 = values.next();
-				co1.accessCount -= minAccessCount;
-				if (co1.accessCount <= 0) {
+				if (co1.accessCount.addAndGet(-minAccessCount) <= 0) {
 					values.remove();
 					values.remove();
 					onRemove(co1.key, co1.obj);
 					onRemove(co1.key, co1.obj);
 					count++;
 					count++;

+ 2 - 2
hutool-core/src/main/java/cn/hutool/core/date/DateUtil.java

@@ -819,10 +819,10 @@ public class DateUtil extends CalendarUtil {
 		int length = utcString.length();
 		int length = utcString.length();
 		if (StrUtil.contains(utcString, 'Z')) {
 		if (StrUtil.contains(utcString, 'Z')) {
 			if (length == DatePattern.UTC_PATTERN.length() - 4) {
 			if (length == DatePattern.UTC_PATTERN.length() - 4) {
-				// 格式类似:2018-09-13T05:34:31Z
+				// 格式类似:2018-09-13T05:34:31Z,-4表示减去4个单引号的长度
 				return parse(utcString, DatePattern.UTC_FORMAT);
 				return parse(utcString, DatePattern.UTC_FORMAT);
 			} else if (length == DatePattern.UTC_MS_PATTERN.length() - 4) {
 			} else if (length == DatePattern.UTC_MS_PATTERN.length() - 4) {
-				// 格式类似:2018-09-13T05:34:31.999Z
+				// 格式类似:2018-09-13T05:34:31.999Z,-4表示减去4个单引号的长度
 				return parse(utcString, DatePattern.UTC_MS_FORMAT);
 				return parse(utcString, DatePattern.UTC_MS_FORMAT);
 			}
 			}
 		} else {
 		} else {