mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-07-21 15:09:48 +08:00
add groupTimeInterval
This commit is contained in:
@@ -21,6 +21,8 @@
|
|||||||
* 【core 】 ArrayUtil增加shuffle方法(pr#1255@Github)
|
* 【core 】 ArrayUtil增加shuffle方法(pr#1255@Github)
|
||||||
* 【core 】 ArrayUtil部分方法分离至PrimitiveArrayUtil
|
* 【core 】 ArrayUtil部分方法分离至PrimitiveArrayUtil
|
||||||
* 【crypto 】 opt改为otp包(issue#1257@Github)
|
* 【crypto 】 opt改为otp包(issue#1257@Github)
|
||||||
|
* 【cache 】 增加CacheListener(issue#1257@Github)
|
||||||
|
* 【core 】 TimeInterval支持分组(issue#1238@Github)
|
||||||
|
|
||||||
### Bug修复
|
### Bug修复
|
||||||
* 【cron 】 修复CronTimer可能死循环的问题(issue#1224@Github)
|
* 【cron 】 修复CronTimer可能死循环的问题(issue#1224@Github)
|
||||||
|
@@ -45,7 +45,6 @@ public interface Cache<K, V> extends Iterable<V>, Serializable {
|
|||||||
* @param key 键
|
* @param key 键
|
||||||
* @param object 缓存的对象
|
* @param object 缓存的对象
|
||||||
* @param timeout 失效时长,单位毫秒
|
* @param timeout 失效时长,单位毫秒
|
||||||
* @see Cache#put(Object, Object, long)
|
|
||||||
*/
|
*/
|
||||||
void put(K key, V object, long timeout);
|
void put(K key, V object, long timeout);
|
||||||
|
|
||||||
@@ -159,4 +158,15 @@ public interface Cache<K, V> extends Iterable<V>, Serializable {
|
|||||||
* @return 是否包含key
|
* @return 是否包含key
|
||||||
*/
|
*/
|
||||||
boolean containsKey(K key);
|
boolean containsKey(K key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设置监听
|
||||||
|
*
|
||||||
|
* @param listener 监听
|
||||||
|
* @return this
|
||||||
|
* @since 5.5.2
|
||||||
|
*/
|
||||||
|
default Cache<K, V> setListener(CacheListener<K, V> listener){
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
20
hutool-cache/src/main/java/cn/hutool/cache/CacheListener.java
vendored
Normal file
20
hutool-cache/src/main/java/cn/hutool/cache/CacheListener.java
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package cn.hutool.cache;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存监听,用于实现缓存操作时的回调监听,例如缓存对象的移除事件等
|
||||||
|
*
|
||||||
|
* @param <K> 缓存键
|
||||||
|
* @param <V> 缓存值
|
||||||
|
* @author looly
|
||||||
|
* @since 5.5.2
|
||||||
|
*/
|
||||||
|
public interface CacheListener<K, V> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对象移除回调
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @param cachedObject 被缓存的对象
|
||||||
|
*/
|
||||||
|
void onRemove(K key, V cachedObject);
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
package cn.hutool.cache.impl;
|
package cn.hutool.cache.impl;
|
||||||
|
|
||||||
import cn.hutool.cache.Cache;
|
import cn.hutool.cache.Cache;
|
||||||
|
import cn.hutool.cache.CacheListener;
|
||||||
import cn.hutool.core.collection.CopiedIter;
|
import cn.hutool.core.collection.CopiedIter;
|
||||||
import cn.hutool.core.lang.func.Func0;
|
import cn.hutool.core.lang.func.Func0;
|
||||||
|
|
||||||
@@ -51,6 +52,11 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
|||||||
*/
|
*/
|
||||||
protected AtomicLong missCount = new AtomicLong();
|
protected AtomicLong missCount = new AtomicLong();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 缓存监听
|
||||||
|
*/
|
||||||
|
protected CacheListener<K, V> listener;
|
||||||
|
|
||||||
// ---------------------------------------------------------------- put start
|
// ---------------------------------------------------------------- put start
|
||||||
@Override
|
@Override
|
||||||
public void put(K key, V object) {
|
public void put(K key, V object) {
|
||||||
@@ -164,7 +170,7 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
|||||||
|
|
||||||
if (co.isExpired()) {
|
if (co.isExpired()) {
|
||||||
missCount.getAndIncrement();
|
missCount.getAndIncrement();
|
||||||
} else{
|
} else {
|
||||||
// 命中
|
// 命中
|
||||||
hitCount.getAndIncrement();
|
hitCount.getAndIncrement();
|
||||||
return co.get(isUpdateLastAccess);
|
return co.get(isUpdateLastAccess);
|
||||||
@@ -280,13 +286,29 @@ public abstract class AbstractCache<K, V> implements Cache<K, V> {
|
|||||||
// ---------------------------------------------------------------- common end
|
// ---------------------------------------------------------------- common end
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 对象移除回调。默认无动作
|
* 设置监听
|
||||||
|
*
|
||||||
|
* @param listener 监听
|
||||||
|
* @return this
|
||||||
|
* @since 5.5.2
|
||||||
|
*/
|
||||||
|
public AbstractCache<K, V> setListener(CacheListener<K, V> listener) {
|
||||||
|
this.listener = listener;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 对象移除回调。默认无动作<br>
|
||||||
|
* 子类可重写此方法用于监听移除事件,如果重写,listener将无效
|
||||||
*
|
*
|
||||||
* @param key 键
|
* @param key 键
|
||||||
* @param cachedObject 被缓存的对象
|
* @param cachedObject 被缓存的对象
|
||||||
*/
|
*/
|
||||||
protected void onRemove(K key, V cachedObject) {
|
protected void onRemove(K key, V cachedObject) {
|
||||||
// ignore
|
final CacheListener<K, V> listener = this.listener;
|
||||||
|
if (null != listener) {
|
||||||
|
listener.onRemove(key, cachedObject);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -18,6 +18,12 @@ public class CacheTest {
|
|||||||
@Test
|
@Test
|
||||||
public void fifoCacheTest(){
|
public void fifoCacheTest(){
|
||||||
Cache<String,String> fifoCache = CacheUtil.newFIFOCache(3);
|
Cache<String,String> fifoCache = CacheUtil.newFIFOCache(3);
|
||||||
|
fifoCache.setListener((key, value)->{
|
||||||
|
// 监听测试,此测试中只有key1被移除,测试是否监听成功
|
||||||
|
Assert.assertEquals("key1", key);
|
||||||
|
Assert.assertEquals("value1", value);
|
||||||
|
});
|
||||||
|
|
||||||
fifoCache.put("key1", "value1", DateUnit.SECOND.getMillis() * 3);
|
fifoCache.put("key1", "value1", DateUnit.SECOND.getMillis() * 3);
|
||||||
fifoCache.put("key2", "value2", DateUnit.SECOND.getMillis() * 3);
|
fifoCache.put("key2", "value2", DateUnit.SECOND.getMillis() * 3);
|
||||||
fifoCache.put("key3", "value3", DateUnit.SECOND.getMillis() * 3);
|
fifoCache.put("key3", "value3", DateUnit.SECOND.getMillis() * 3);
|
||||||
|
@@ -0,0 +1,177 @@
|
|||||||
|
package cn.hutool.core.date;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分组计时器<br>
|
||||||
|
* 计算某几个过程花费的时间,精确到毫秒或纳秒
|
||||||
|
*
|
||||||
|
* @author Looly
|
||||||
|
* @since 5.5.2
|
||||||
|
*/
|
||||||
|
public class GroupTimeInterval implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final boolean isNano;
|
||||||
|
protected final Map<String, Long> groupMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
*
|
||||||
|
* @param isNano 是否使用纳秒计数,false则使用毫秒
|
||||||
|
*/
|
||||||
|
public GroupTimeInterval(boolean isNano) {
|
||||||
|
this.isNano = isNano;
|
||||||
|
groupMap = new ConcurrentHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清空所有定时记录
|
||||||
|
*
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
public GroupTimeInterval clear(){
|
||||||
|
this.groupMap.clear();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始计时并返回当前时间
|
||||||
|
*
|
||||||
|
* @param id 分组ID
|
||||||
|
* @return 开始计时并返回当前时间
|
||||||
|
*/
|
||||||
|
public long start(String id) {
|
||||||
|
final long time = getTime();
|
||||||
|
this.groupMap.put(id, time);
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 重新计时并返回从开始到当前的持续时间秒<br>
|
||||||
|
* 如果此分组下没有记录,则返回0;
|
||||||
|
*
|
||||||
|
* @param id 分组ID
|
||||||
|
* @return 重新计时并返回从开始到当前的持续时间
|
||||||
|
*/
|
||||||
|
public long intervalRestart(String id) {
|
||||||
|
final long now = getTime();
|
||||||
|
return now - ObjectUtil.defaultIfNull(this.groupMap.put(id, now), now);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------- Interval
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从开始到当前的间隔时间(毫秒数)<br>
|
||||||
|
* 如果使用纳秒计时,返回纳秒差,否则返回毫秒差<br>
|
||||||
|
* 如果分组下没有开始时间,返回{@code null}
|
||||||
|
*
|
||||||
|
* @param id 分组ID
|
||||||
|
* @return 从开始到当前的间隔时间(毫秒数)
|
||||||
|
*/
|
||||||
|
public long interval(String id) {
|
||||||
|
final Long lastTime = this.groupMap.get(id);
|
||||||
|
if (null == lastTime) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return getTime() - lastTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从开始到当前的间隔时间
|
||||||
|
*
|
||||||
|
* @param id 分组ID
|
||||||
|
* @param dateUnit 时间单位
|
||||||
|
* @return 从开始到当前的间隔时间(毫秒数)
|
||||||
|
*/
|
||||||
|
public long interval(String id, DateUnit dateUnit) {
|
||||||
|
final long intervalMs = isNano ? interval(id) / 1000000L : interval(id);
|
||||||
|
if (DateUnit.MS == dateUnit) {
|
||||||
|
return intervalMs;
|
||||||
|
}
|
||||||
|
return intervalMs / dateUnit.getMillis();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从开始到当前的间隔时间(毫秒数)
|
||||||
|
*
|
||||||
|
* @param id 分组ID
|
||||||
|
* @return 从开始到当前的间隔时间(毫秒数)
|
||||||
|
*/
|
||||||
|
public long intervalMs(String id) {
|
||||||
|
return interval(id, DateUnit.MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从开始到当前的间隔秒数,取绝对值
|
||||||
|
*
|
||||||
|
* @param id 分组ID
|
||||||
|
* @return 从开始到当前的间隔秒数,取绝对值
|
||||||
|
*/
|
||||||
|
public long intervalSecond(String id) {
|
||||||
|
return interval(id, DateUnit.SECOND);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从开始到当前的间隔分钟数,取绝对值
|
||||||
|
*
|
||||||
|
* @param id 分组ID
|
||||||
|
* @return 从开始到当前的间隔分钟数,取绝对值
|
||||||
|
*/
|
||||||
|
public long intervalMinute(String id) {
|
||||||
|
return interval(id, DateUnit.MINUTE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从开始到当前的间隔小时数,取绝对值
|
||||||
|
*
|
||||||
|
* @param id 分组ID
|
||||||
|
* @return 从开始到当前的间隔小时数,取绝对值
|
||||||
|
*/
|
||||||
|
public long intervalHour(String id) {
|
||||||
|
return interval(id, DateUnit.HOUR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从开始到当前的间隔天数,取绝对值
|
||||||
|
*
|
||||||
|
* @param id 分组ID
|
||||||
|
* @return 从开始到当前的间隔天数,取绝对值
|
||||||
|
*/
|
||||||
|
public long intervalDay(String id) {
|
||||||
|
return interval(id, DateUnit.DAY);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从开始到当前的间隔周数,取绝对值
|
||||||
|
*
|
||||||
|
* @param id 分组ID
|
||||||
|
* @return 从开始到当前的间隔周数,取绝对值
|
||||||
|
*/
|
||||||
|
public long intervalWeek(String id) {
|
||||||
|
return interval(id, DateUnit.WEEK);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从开始到当前的间隔时间(毫秒数),返回XX天XX小时XX分XX秒XX毫秒
|
||||||
|
*
|
||||||
|
* @param id 分组ID
|
||||||
|
* @return 从开始到当前的间隔时间(毫秒数)
|
||||||
|
*/
|
||||||
|
public String intervalPretty(String id) {
|
||||||
|
return DateUtil.formatBetween(intervalMs(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取时间的毫秒或纳秒数,纳秒非时间戳
|
||||||
|
*
|
||||||
|
* @return 时间
|
||||||
|
*/
|
||||||
|
private long getTime() {
|
||||||
|
return this.isNano ? System.nanoTime() : System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
package cn.hutool.core.date;
|
package cn.hutool.core.date;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计时器<br>
|
* 计时器<br>
|
||||||
@@ -8,11 +8,9 @@ import java.io.Serializable;
|
|||||||
*
|
*
|
||||||
* @author Looly
|
* @author Looly
|
||||||
*/
|
*/
|
||||||
public class TimeInterval implements Serializable {
|
public class TimeInterval extends GroupTimeInterval {
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
|
private static final String DEFAULT_ID = StrUtil.EMPTY;
|
||||||
private long time;
|
|
||||||
private final boolean isNano;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造,默认使用毫秒计数
|
* 构造,默认使用毫秒计数
|
||||||
@@ -23,10 +21,11 @@ public class TimeInterval implements Serializable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 构造
|
* 构造
|
||||||
|
*
|
||||||
* @param isNano 是否使用纳秒计数,false则使用毫秒
|
* @param isNano 是否使用纳秒计数,false则使用毫秒
|
||||||
*/
|
*/
|
||||||
public TimeInterval(boolean isNano) {
|
public TimeInterval(boolean isNano) {
|
||||||
this.isNano = isNano;
|
super(isNano);
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,28 +33,25 @@ public class TimeInterval implements Serializable {
|
|||||||
* @return 开始计时并返回当前时间
|
* @return 开始计时并返回当前时间
|
||||||
*/
|
*/
|
||||||
public long start() {
|
public long start() {
|
||||||
time = getTime(isNano);
|
return start(DEFAULT_ID);
|
||||||
return time;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return 重新计时并返回从开始到当前的持续时间
|
* @return 重新计时并返回从开始到当前的持续时间
|
||||||
*/
|
*/
|
||||||
public long intervalRestart() {
|
public long intervalRestart() {
|
||||||
long now = getTime(isNano);
|
return intervalRestart(DEFAULT_ID);
|
||||||
long d = now - time;
|
|
||||||
time = now;
|
|
||||||
return d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 重新开始计算时间(重置开始时间)
|
* 重新开始计算时间(重置开始时间)
|
||||||
*
|
*
|
||||||
* @return this
|
* @return this
|
||||||
|
* @see #start()
|
||||||
* @since 3.0.1
|
* @since 3.0.1
|
||||||
*/
|
*/
|
||||||
public TimeInterval restart() {
|
public TimeInterval restart() {
|
||||||
time = getTime(isNano);
|
start(DEFAULT_ID);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +64,7 @@ public class TimeInterval implements Serializable {
|
|||||||
* @return 从开始到当前的间隔时间(毫秒数)
|
* @return 从开始到当前的间隔时间(毫秒数)
|
||||||
*/
|
*/
|
||||||
public long interval() {
|
public long interval() {
|
||||||
return getTime(isNano) - time;
|
return interval(DEFAULT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -78,7 +74,7 @@ public class TimeInterval implements Serializable {
|
|||||||
* @since 4.6.7
|
* @since 4.6.7
|
||||||
*/
|
*/
|
||||||
public String intervalPretty() {
|
public String intervalPretty() {
|
||||||
return DateUtil.formatBetween(intervalMs());
|
return intervalPretty(DEFAULT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,7 +83,7 @@ public class TimeInterval implements Serializable {
|
|||||||
* @return 从开始到当前的间隔时间(毫秒数)
|
* @return 从开始到当前的间隔时间(毫秒数)
|
||||||
*/
|
*/
|
||||||
public long intervalMs() {
|
public long intervalMs() {
|
||||||
return isNano ? interval() / 1000000L : interval();
|
return intervalMs(DEFAULT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -96,7 +92,7 @@ public class TimeInterval implements Serializable {
|
|||||||
* @return 从开始到当前的间隔秒数,取绝对值
|
* @return 从开始到当前的间隔秒数,取绝对值
|
||||||
*/
|
*/
|
||||||
public long intervalSecond() {
|
public long intervalSecond() {
|
||||||
return intervalMs() / DateUnit.SECOND.getMillis();
|
return intervalSecond(DEFAULT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -105,7 +101,7 @@ public class TimeInterval implements Serializable {
|
|||||||
* @return 从开始到当前的间隔分钟数,取绝对值
|
* @return 从开始到当前的间隔分钟数,取绝对值
|
||||||
*/
|
*/
|
||||||
public long intervalMinute() {
|
public long intervalMinute() {
|
||||||
return intervalMs() / DateUnit.MINUTE.getMillis();
|
return intervalMinute(DEFAULT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -114,7 +110,7 @@ public class TimeInterval implements Serializable {
|
|||||||
* @return 从开始到当前的间隔小时数,取绝对值
|
* @return 从开始到当前的间隔小时数,取绝对值
|
||||||
*/
|
*/
|
||||||
public long intervalHour() {
|
public long intervalHour() {
|
||||||
return intervalMs() / DateUnit.HOUR.getMillis();
|
return intervalHour(DEFAULT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -123,7 +119,7 @@ public class TimeInterval implements Serializable {
|
|||||||
* @return 从开始到当前的间隔天数,取绝对值
|
* @return 从开始到当前的间隔天数,取绝对值
|
||||||
*/
|
*/
|
||||||
public long intervalDay() {
|
public long intervalDay() {
|
||||||
return intervalMs() / DateUnit.DAY.getMillis();
|
return intervalDay(DEFAULT_ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,16 +128,6 @@ public class TimeInterval implements Serializable {
|
|||||||
* @return 从开始到当前的间隔周数,取绝对值
|
* @return 从开始到当前的间隔周数,取绝对值
|
||||||
*/
|
*/
|
||||||
public long intervalWeek() {
|
public long intervalWeek() {
|
||||||
return intervalMs() / DateUnit.WEEK.getMillis();
|
return intervalWeek(DEFAULT_ID);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取时间的毫秒或纳秒数,纳秒非时间戳
|
|
||||||
*
|
|
||||||
* @param isNano 是否为高精度时间
|
|
||||||
* @return 时间
|
|
||||||
*/
|
|
||||||
private static long getTime(boolean isNano) {
|
|
||||||
return isNano ? System.nanoTime() : System.currentTimeMillis();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,10 @@ public class ConcurrencyTester {
|
|||||||
private final TimeInterval timeInterval;
|
private final TimeInterval timeInterval;
|
||||||
private long interval;
|
private long interval;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构造
|
||||||
|
* @param threadSize 线程数
|
||||||
|
*/
|
||||||
public ConcurrencyTester(int threadSize) {
|
public ConcurrencyTester(int threadSize) {
|
||||||
this.sf = new SyncFinisher(threadSize);
|
this.sf = new SyncFinisher(threadSize);
|
||||||
this.timeInterval = new TimeInterval();
|
this.timeInterval = new TimeInterval();
|
||||||
|
@@ -0,0 +1,20 @@
|
|||||||
|
package cn.hutool.core.date;
|
||||||
|
|
||||||
|
import cn.hutool.core.lang.Console;
|
||||||
|
import cn.hutool.core.thread.ThreadUtil;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TimeIntervalTest {
|
||||||
|
@Test
|
||||||
|
public void intervalGroupTest(){
|
||||||
|
final TimeInterval timer = new TimeInterval();
|
||||||
|
timer.start("1");
|
||||||
|
ThreadUtil.sleep(800);
|
||||||
|
timer.start("2");
|
||||||
|
ThreadUtil.sleep(900);
|
||||||
|
|
||||||
|
|
||||||
|
Console.log("Timer 1 took {} ms", timer.intervalMs("1"));
|
||||||
|
Console.log("Timer 2 took {} ms", timer.intervalMs("2"));
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user