系统中有很多地方需要统计一个方法执行完毕,所花费的时间。
有的需求是在统计一个大任务时, 同时分段统计子任务所花费的时间。
比较常见的统计比如统计servlet执行所花费的时间, 可以写一个filter对servlet做拦截 。 对FilterChain的doFilter()方法计时。
写了一个TimerUtil的实现如下:
package timer;
import java.util.Stack;
/**
* 计时工具类
* 用于给程序中的方法计时,来跟踪那些比较耗时的方法
* 使用 ThreadLocal实现,可以安全的在多线程当中执行
* 并支持子任务
* @author zhoufeng
*/
public class TimerUtil {
private static final ThreadLocal<Stack<TimerEntry>> timerEntry = new ThreadLocal<Stack<TimerEntry>>() ;
/**
* 开始一个计时器
* @param name
*/
public static void start(String name) {
Stack<TimerEntry> timerEntries = timerEntry.get() ;
if(timerEntries == null){
timerEntries = new Stack<TimerEntry>();
timerEntry.set(timerEntries) ;
}
TimerEntry entry = new TimerEntry() ;
entry.name = name ;
entry.startTiem = System.currentTimeMillis() ;
entry.stopTime = -1 ;
timerEntries.push(entry) ;
}
/**
* 结束当前的计时器
* @return返回当前计时器花费的时间(毫秒)
*/
public static long timing() {
TimerEntry currentEntry = getCurrentTimerEntry();
if(currentEntry != null){
currentEntry.stopTime = System.currentTimeMillis() ;
long timeConsuming = currentEntry.stopTime - currentEntry.startTiem ;
timerEntry.get().pop();
return timeConsuming ;
}
return -1;
}
/**
* 此方法应该在timing()方法之前调用 ,因为timing()方法操作完之后,会将当前的计时任务pop出栈
* @return当前计时器的名字
*/
public static String getCurrentNameTimerName(){
TimerEntry currentEntry = getCurrentTimerEntry();
if(currentEntry != null){
return currentEntry.name ;
}
return null ;
}
/**
* 清除计时器
*/
public static void clear(){
timerEntry.set(null) ;
}
private static TimerEntry getCurrentTimerEntry(){
Stack<TimerEntry> timerEntries = timerEntry.get() ;
if(timerEntries != null){
return timerEntries.peek() ;
}
return null ;
}
private static class TimerEntry{
public String name ;
public long startTiem ;
public long stopTime ;
}
}
写个测试类。 来分别统计m1() m2() m3() 执行所花费的时间。 以及main方法执行完成花费的时间, 代码如下:
package timer;
public class TimerTest {
public static void m1(){
try {
Thread.sleep(1000) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method1 done.");
}
public static void m2(){
try {
Thread.sleep(2000) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method2 done.");
}
public static void m3(){
try {
Thread.sleep(3000) ;
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Method3 done.");
}
public static void main(String[] args) {
long timeConsume ;
long m1Cs ;
long m2Cs ;
long m3Cs ;
try{
TimerUtil.start("total task");
try{
TimerUtil.start("m1()");
m1() ;
}finally{
m1Cs = TimerUtil.timing();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try{
TimerUtil.start("m2()");
m2() ;
}finally{
m2Cs = TimerUtil.timing();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
try{
TimerUtil.start("m3()");
m3() ;
}finally{
m3Cs = TimerUtil.timing();
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}finally{
timeConsume = TimerUtil.timing() ;
}
TimerUtil.clear() ;
System.out.println("m1Cs:" + m1Cs);
System.out.println("m2Cs:" + m2Cs);
System.out.println("m3Cs:" + m3Cs);
System.out.println("totalConsume:" + timeConsume);
}
}
打印结果:
Method1 done.
Method2 done.
Method3 done.
m1Cs:1000
m2Cs:2000
m3Cs:3000
totalConsume:9000