diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/bean/StrictBeanDesc.java b/hutool-core/src/main/java/org/dromara/hutool/core/bean/StrictBeanDesc.java index ff6dfed08..7fc461150 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/bean/StrictBeanDesc.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/bean/StrictBeanDesc.java @@ -198,7 +198,7 @@ public class StrictBeanDesc extends AbstractBeanDesc { private static Method getGetterForBoolean(final Method[] gettersOrSetters, final String fieldName, final boolean ignoreCase) { // 查找isXXX return MethodUtil.getMethod(gettersOrSetters, m -> { - if (0 != m.getParameterCount() || false == BooleanUtil.isBoolean(m.getReturnType())) { + if (0 != m.getParameterCount() || !BooleanUtil.isBoolean(m.getReturnType())) { // getter方法要求无参数且返回boolean或Boolean return false; } @@ -231,7 +231,7 @@ public class StrictBeanDesc extends AbstractBeanDesc { private static Method getSetterForBoolean(final Method[] gettersOrSetters, final String fieldName, final boolean ignoreCase) { // 查找isXXX return MethodUtil.getMethod(gettersOrSetters, m -> { - if (1 != m.getParameterCount() || false == BooleanUtil.isBoolean(m.getParameterTypes()[0])) { + if (1 != m.getParameterCount() || !BooleanUtil.isBoolean(m.getParameterTypes()[0])) { // setter方法要求1个boolean或Boolean参数 return false; } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/cache/impl/StampedCache.java b/hutool-core/src/main/java/org/dromara/hutool/core/cache/impl/StampedCache.java index 74fde715c..015aa44d7 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/cache/impl/StampedCache.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/cache/impl/StampedCache.java @@ -51,12 +51,12 @@ public abstract class StampedCache extends AbstractCache { @Override public boolean containsKey(final K key) { - return null != get(key, false, false); + return null != doGet(key, false, false); } @Override public V get(final K key, final boolean isUpdateLastAccess) { - return get(key, isUpdateLastAccess, true); + return doGet(key, isUpdateLastAccess, true); } @Override @@ -106,19 +106,38 @@ public abstract class StampedCache extends AbstractCache { } /** - * 获取值 + * 获取值,使用乐观锁,但是此方法可能导致读取脏数据,但对于缓存业务可容忍。情况如下: + *
+	 *     1. 读取时无写入,不冲突,直接获取值
+	 *     2. 读取时无写入,但是乐观读时触发了并发异常,此时获取同步锁,获取新值
+	 *     4. 读取时有写入,此时获取同步锁,获取新值
+	 * 
* * @param key 键 * @param isUpdateLastAccess 是否更新最后修改时间 * @param isUpdateCount 是否更新命中数,get时更新,contains时不更新 * @return 值或null */ - private V get(final K key, final boolean isUpdateLastAccess, final boolean isUpdateCount) { + private V doGet(final K key, final boolean isUpdateLastAccess, final boolean isUpdateCount) { // 尝试读取缓存,使用乐观读锁 + CacheObj co = null; long stamp = lock.tryOptimisticRead(); - CacheObj co = getWithoutLock(key); - if (false == lock.validate(stamp)) { - // 有写线程修改了此对象,悲观读 + boolean isReadError = true; + if(lock.validate(stamp)){ + try{ + // 乐观读,可能读取脏数据,在缓存中可容忍,分两种情况 + // 1. 读取时无线程写入 + // 2. 读取时有线程写入,导致数据不一致,此时读取未更新的缓存值 + co = getWithoutLock(key); + isReadError = false; + } catch (final Exception ignore){ + // ignore + } + } + + if(isReadError){ + // 转换为悲观读 + // 原因可能为无锁读时触发并发异常,或者锁被占(正在写) stamp = lock.readLock(); try { co = getWithoutLock(key); @@ -133,7 +152,7 @@ public abstract class StampedCache extends AbstractCache { missCount.increment(); } return null; - } else if (false == co.isExpired()) { + } else if (!co.isExpired()) { if (isUpdateCount) { hitCount.increment(); } @@ -159,7 +178,7 @@ public abstract class StampedCache extends AbstractCache { if (null == co) { return null; } - if (false == co.isExpired()) { + if (!co.isExpired()) { // 首先尝试获取值,如果值存在且有效,返回之 if (isUpdateCount) { hitCount.increment(); diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/date/DateBetween.java b/hutool-core/src/main/java/org/dromara/hutool/core/date/DateBetween.java index debb6e4b3..bf9883730 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/date/DateBetween.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/date/DateBetween.java @@ -152,29 +152,30 @@ public class DateBetween implements Serializable { final Calendar endCal = CalendarUtil.calendar(end); final int result = endCal.get(Calendar.YEAR) - beginCal.get(Calendar.YEAR); - if (false == isReset) { - final int beginMonthBase0 = beginCal.get(Calendar.MONTH); - final int endMonthBase0 = endCal.get(Calendar.MONTH); - if (beginMonthBase0 < endMonthBase0) { - return result; - } else if (beginMonthBase0 > endMonthBase0) { - return result - 1; - } else if (Calendar.FEBRUARY == beginMonthBase0 - && CalendarUtil.isLastDayOfMonth(beginCal) - && CalendarUtil.isLastDayOfMonth(endCal)) { - // 考虑闰年的2月情况 - // 两个日期都位于2月的最后一天,此时月数按照相等对待,此时都设置为1号 - beginCal.set(Calendar.DAY_OF_MONTH, 1); - endCal.set(Calendar.DAY_OF_MONTH, 1); - } - - endCal.set(Calendar.YEAR, beginCal.get(Calendar.YEAR)); - final long between = endCal.getTimeInMillis() - beginCal.getTimeInMillis(); - if (between < 0) { - return result - 1; - } + if(isReset){ + return result; + } + + final int beginMonthBase0 = beginCal.get(Calendar.MONTH); + final int endMonthBase0 = endCal.get(Calendar.MONTH); + if (beginMonthBase0 < endMonthBase0) { + return result; + } else if (beginMonthBase0 > endMonthBase0) { + return result - 1; + } else if (Calendar.FEBRUARY == beginMonthBase0 + && CalendarUtil.isLastDayOfMonth(beginCal) + && CalendarUtil.isLastDayOfMonth(endCal)) { + // 考虑闰年的2月情况 + // 两个日期都位于2月的最后一天,此时月数按照相等对待,此时都设置为1号 + beginCal.set(Calendar.DAY_OF_MONTH, 1); + endCal.set(Calendar.DAY_OF_MONTH, 1); + } + + endCal.set(Calendar.YEAR, beginCal.get(Calendar.YEAR)); + final long between = endCal.getTimeInMillis() - beginCal.getTimeInMillis(); + if (between < 0) { + return result - 1; } - return result; } /** diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileTypeUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileTypeUtil.java index 0dc1609e1..fe7796ce6 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileTypeUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileTypeUtil.java @@ -221,7 +221,7 @@ public class FileTypeUtil { * @throws IORuntimeException 读取文件引起的异常 */ public static String getType(final File file, final boolean isExact) throws IORuntimeException { - if (false == FileUtil.isFile(file)) { + if (!FileUtil.isFile(file)) { throw new IllegalArgumentException("Not a regular file!"); } InputStream in = null; diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java index e96857acd..25a869549 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/file/FileUtil.java @@ -584,9 +584,7 @@ public class FileUtil { * @since 5.8.28 */ public static int getTotalLines(final File file, final int bufferSize) { - if (false == isFile(file)) { - throw new IORuntimeException("Input must be a File"); - } + Assert.isTrue(isFile(file), ()-> new IORuntimeException("Input must be a File")); try (final LineCounter lineCounter = new LineCounter(getInputStream(file), bufferSize)) { return lineCounter.getCount(); } catch (final IOException e) { @@ -778,7 +776,7 @@ public class FileUtil { * @since 4.5.5 */ public static boolean cleanEmpty(final File directory) throws IORuntimeException { - if (directory == null || false == directory.exists() || false == directory.isDirectory()) { + if (directory == null || !directory.exists() || !directory.isDirectory()) { return true; } diff --git a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSftp.java b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSftp.java index 7f4a9dc74..ee3bad669 100644 --- a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSftp.java +++ b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschSftp.java @@ -201,7 +201,7 @@ public class JschSftp extends AbstractFtp { * @since 4.1.14 */ public ChannelSftp getClient() { - if (false == this.channel.isConnected()) { + if (!this.channel.isConnected()) { init(); } return this.channel; diff --git a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschUtil.java b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschUtil.java index cc2f665df..797a6e8de 100644 --- a/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschUtil.java +++ b/hutool-extra/src/main/java/org/dromara/hutool/extra/ssh/engine/jsch/JschUtil.java @@ -89,7 +89,7 @@ public class JschUtil { public static Channel createChannel(final Session session, final ChannelType channelType, final long timeout) { final Channel channel; try { - if (false == session.isConnected()) { + if (!session.isConnected()) { session.connect((int) timeout); } channel = session.openChannel(channelType.getValue()); diff --git a/hutool-http/src/main/java/org/dromara/hutool/http/useragent/UserAgentParser.java b/hutool-http/src/main/java/org/dromara/hutool/http/useragent/UserAgentParser.java index 419a7e873..4394b4be0 100644 --- a/hutool-http/src/main/java/org/dromara/hutool/http/useragent/UserAgentParser.java +++ b/hutool-http/src/main/java/org/dromara/hutool/http/useragent/UserAgentParser.java @@ -59,7 +59,7 @@ public class UserAgentParser { // issue#IA74K2 MACOS下的微信不属于移动平台 if(platform.isMobile() || browser.isMobile()){ - if(false == os.isMacOS()){ + if(!os.isMacOS()){ userAgent.setMobile(true); } }