使用ThreadLocal配合StopWatch简化代码耗时打印的代码量。
工具类提供StopWatch默认输出格式和支持自定义打印输出格式,具体代码如下:
import org.springframework.util.StopWatch;
import lombok.extern.slf4j.Slf4j;
/**
* 使用线程变量全局打印耗时
*
* @author jun.chen
*
*/
@Slf4j
public class CostPrintUtil {
private static final ThreadLocal<StopWatch> stopWatchLocal = new ThreadLocal<>();
/**
* 初始化StopWatch
*
* @param title
*/
public static void init(String title) {
initStopWatch(title);
}
/**
* 开始记录某段代码的耗时
*
* @param taskName
*/
public static void startWatch(String taskName) {
StopWatch stopWatch = getStopWatch();
if (stopWatch.isRunning()) {
stopWatch.stop();
log.debug("{} is Running,stop it.", stopWatch.getLastTaskName());
}
stopWatch.start(taskName);
}
/**
* 结束记录
*
* @param taskName
*/
public static void stopWatch() {
StopWatch stopWatch = getStopWatch();
if (stopWatch.isRunning()) {
stopWatch.stop();
} else {
log.debug("stopWatch is not start.");
}
}
/**
* 结束StopWatch并StopWatch对象
*
* @return
*/
public static StopWatch end() {
StopWatch stopWatch = getStopWatch(true);
if (null == stopWatch) {
throw new RuntimeException("当前线程内没有StopWatch对象.");
}
if (stopWatch.isRunning()) {
stopWatch.stop();
log.debug("{} is Runnong,stop it.", stopWatch.getLastTaskName());
}
clearStopWatch();
return stopWatch;
}
/**
* 结束并打印 默认使用stopWatch.prettyPrint()
*
*/
public static void endPrint() {
endPrint(null);
}
/**
* 结束并打印
*
* @param helper
*/
public static void endPrint(PrintHelper helper) {
StopWatch stopWatch = end();
if (null != helper) {
helper.print(stopWatch);
} else {
log.info(stopWatch.prettyPrint());
}
}
/**
* 自定义打印输出
*
* @author jun.chen
*
*/
interface PrintHelper {
void print(StopWatch stopWatch);
}
private static void initStopWatch(String title) {
stopWatchLocal.set(new StopWatch(title));
}
private static StopWatch getStopWatch() {
return getStopWatch(false);
}
private static StopWatch getStopWatch(boolean isEnd) {
return getStopWatch("", isEnd);
}
/**
* 获取当前线程内的StopWatch
*
* @param title
* @param isEnd
* @return
*/
private static StopWatch getStopWatch(String title, boolean isEnd) {
StopWatch stopWatch = stopWatchLocal.get();
// 非结束时获取StopWatch允许初始化
if (null == stopWatch && !isEnd) {
initStopWatch(title);
}
return stopWatchLocal.get();
}
private static void clearStopWatch() {
stopWatchLocal.remove();
}
public static void main(String[] args) throws InterruptedException {
// a. 正常使用
CostPrintUtil.init("示例A");
CostPrintUtil.startWatch("TaskA - 1");
Thread.sleep(200);
CostPrintUtil.stopWatch();
CostPrintUtil.startWatch("TaskA - 2");
Thread.sleep(300);
CostPrintUtil.stopWatch();
CostPrintUtil.startWatch("TaskA - 3");
Thread.sleep(100);
CostPrintUtil.stopWatch();
CostPrintUtil.endPrint();
// b. 未初始化直接start
CostPrintUtil.startWatch("TaskB - 1");
Thread.sleep(200);
CostPrintUtil.stopWatch();
CostPrintUtil.endPrint();
// c. 未stop直接end
CostPrintUtil.startWatch("TaskC - 1");
Thread.sleep(200);
CostPrintUtil.endPrint();
// d. 多次end
CostPrintUtil.startWatch("TaskD - 1");
Thread.sleep(200);
CostPrintUtil.endPrint();
try {
CostPrintUtil.endPrint();
} catch (Exception e) {
log.error(e.getMessage());
}
// e.多次start 和 多次stop
CostPrintUtil.startWatch("TaskE - 1");
Thread.sleep(200);
CostPrintUtil.startWatch("TaskE - 2");
Thread.sleep(200);
CostPrintUtil.stopWatch();
CostPrintUtil.stopWatch();
CostPrintUtil.endPrint();
// f. 自定义打印输出
CostPrintUtil.startWatch("自定义打印耗时(重写接口实现)");
Thread.sleep(200);
CostPrintUtil.stopWatch();
// 重写接口实现
CostPrintUtil.endPrint(new PrintHelper() {
@Override
public void print(StopWatch stopWatch) {
log.info("TaskName:{} Cost:{}", stopWatch.getLastTaskName(), stopWatch.getTotalTimeSeconds());
}
});
// 使用lambda表达式
CostPrintUtil.startWatch("自定义打印耗时(lambda表达式)");
Thread.sleep(200);
CostPrintUtil.stopWatch();
CostPrintUtil.endPrint((stopWatch) -> {
String lastTaskName = stopWatch.getLastTaskName();
long lastTaskTimeMillis = stopWatch.getLastTaskTimeMillis();
log.info("Task: {} Costs: {}ms", lastTaskName, lastTaskTimeMillis);
});
}
}
其中main函数提供了一些使用示例,有疑问或有改善意见的欢迎留言 ( ^_^ )。