系統中有很多地方需要統計一個方法執行完畢,所花費的時間。
有的需求是在統計一個大任務時, 同時分段統計子任務所花費的時間。
比較常見的統計比如統計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