Java計算代碼段執(zhí)行時間的詳細過程
前言
在日常開發(fā)功能時,同一種功能可能會有多種實現(xiàn)方式。我們需要做一個取舍。
最常見的條件就是性能、可讀性、可維護性。
本篇文章,我們主要討論“性能”。
場景
假設我們現(xiàn)在需要計算一段代碼的運行時間。
最常見的寫法是,在執(zhí)行這段代碼前,獲得一下當前的時間戳,在執(zhí)行這段代碼后,獲取一下當前的時間戳,然后倆時間相減,就是花費時間了。
但有時,我們需要將這段代碼執(zhí)行多次。
這種場景是,執(zhí)行的時間戳很小,沒有可比性。比如執(zhí)行一段代碼,運行時間是 0 或者 2毫秒。
這種時候你可能會說,那就用一個for循環(huán),執(zhí)行多次,計算平均時間就好了。
問題來了,如果這種相似的操作,寫的多了呢,用的地方很多呢?
我們現(xiàn)在就需要將它給寫成一套模板,只需要簡單的填充參數(shù),調用,就能實現(xiàn)上述的功能。
代碼實現(xiàn)
MethodBody 接口定義
這個接口主要是用于填充代碼段,因此設計為函數(shù)式接口,方便調用。
package org.feng.calc;
/**
* 運行的方法內(nèi)容:使用Lambda
*
* @version V1.0
*/
@FunctionalInterface
public interface MethodBody {
void run();
}
CalcExecuteTimeResult 運行結果實體
package org.feng.calc;
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* 計算執(zhí)行時間的結果保存
*
* @version V1.0
*/
@Data
public class CalcExecuteTimeResult {
/**
* 執(zhí)行代碼花費的時間
*/
private List<Long> costTime;
public CalcExecuteTimeResult(int size) {
costTime = new ArrayList<>(size);
}
}
ExecuteTemplate 執(zhí)行模板定義
package org.feng.calc;
import lombok.Getter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
/**
* 執(zhí)行模板
*
* @version V1.0
*/
public class ExecuteTemplate {
private final List<MethodBody> methodBodyList;
@Getter
private CalcExecuteTimeResult calcExecuteTimeResult;
public ExecuteTemplate() {
this.methodBodyList = new ArrayList<>();
}
public void addMethod(MethodBody methodBody) {
methodBodyList.add(methodBody);
}
/**
* 執(zhí)行
*
* @param timeUnit 時間單位
* @param frequency 頻次-單個方法{@link MethodBody}實例執(zhí)行的次數(shù)
*/
void process(TimeUnit timeUnit, long frequency) {
this.calcExecuteTimeResult = new CalcExecuteTimeResult(methodBodyList.size());
List<Long> costTime = calcExecuteTimeResult.getCostTime();
for (MethodBody methodBody : methodBodyList) {
long startTime = getTime(timeUnit);
for (int i = 0; i < frequency; i++) {
methodBody.run();
}
long endTime = getTime(timeUnit);
costTime.add(endTime - startTime);
}
}
private long getTime(TimeUnit timeUnit) {
if (!SUPPORTED_TIME_UNIT.contains(timeUnit)) {
throw new UnsupportedOperationException("不支持的時間單位:" + timeUnit);
}
if (TimeUnit.NANOSECONDS.equals(timeUnit)) {
return System.nanoTime();
}
return System.currentTimeMillis();
}
/**
* 當前支持的時間單位
*/
private static final Set<TimeUnit> SUPPORTED_TIME_UNIT = Set.of(TimeUnit.MILLISECONDS, TimeUnit.NANOSECONDS);
}
CalcExecuteTimeContext 計算執(zhí)行時間上下文
package org.feng.calc;
import lombok.Setter;
import lombok.experimental.Accessors;
import java.util.concurrent.TimeUnit;
/**
* 計算執(zhí)行時間-上下文
*
* @version V1.0
*/
@Setter
@Accessors(chain = true)
public class CalcExecuteTimeContext {
private TimeUnit timeUnit;
private Long frequency;
private ExecuteTemplate executeTemplate;
public CalcExecuteTimeResult run() {
executeTemplate.process(timeUnit, frequency);
return executeTemplate.getCalcExecuteTimeResult();
}
public void addMethod(MethodBody methodBody){
executeTemplate.addMethod(methodBody);
}
}
測試運行
package org.feng.calc;
import java.util.concurrent.TimeUnit;
/**
* 測試運行
*
* @version v1.0
*/
public class Client {
public static void main(String[] args) {
// 初始化上下文:設置每個方法執(zhí)行的次數(shù),以及計算時間時使用的時間單位,執(zhí)行模板
CalcExecuteTimeContext context = new CalcExecuteTimeContext()
.setFrequency(2L)
.setTimeUnit(TimeUnit.MILLISECONDS)
.setExecuteTemplate(new ExecuteTemplate());
context.addMethod(() -> {
System.out.println(111);
System.out.println(111);
System.out.println(111);
System.out.println(111);
System.out.println(111);
});
context.addMethod(() -> {
System.out.println(222);
System.out.println(222);
System.out.println(222);
System.out.println(222);
System.out.println(222);
});
// 計算得到方法運行的結果
CalcExecuteTimeResult executeTimeResult = context.run();
System.out.println(executeTimeResult);
}
}
運行結果:
111
111
111
111
111
111
111
111
111
111
222
222
222
222
222
222
222
222
222
222
CalcExecuteTimeResult(costTime=[0, 1])
到此這篇關于Java計算代碼段執(zhí)行時間的詳細過程的文章就介紹到這了,更多相關Java代碼段執(zhí)行時間內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Java關鍵字finally_動力節(jié)點Java學院整理
java關鍵字finally不管是否出現(xiàn)異常,finally子句總是在塊完成之前執(zhí)行。下面通過實現(xiàn)代碼給大家介紹Java關鍵字finally相關知識,需要的的朋友參考下吧2017-04-04
SSH框架網(wǎng)上商城項目第12戰(zhàn)之添加和更新商品功能
這篇文章主要介紹了SSH框架網(wǎng)上商城項目第12戰(zhàn)之添加和更新商品功能的實現(xiàn)代碼,感興趣的小伙伴們可以參考一下2016-06-06
SpringBoot使用開發(fā)環(huán)境application.properties問題
這篇文章主要介紹了SpringBoot使用開發(fā)環(huán)境application.properties問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-07-07
Spring?Boot項目獲取resources目錄下文件并返回給前端的方案
我們在項目中經(jīng)常碰到需要讀取固定文件的場景,如模板文件,一般做法是將文件放在resources目錄下,程序通過多種方式可以順利讀取文件,這篇文章主要給大家介紹了關于Spring?Boot項目獲取resources目錄下文件并返回給前端的相關資料,需要的朋友可以參考下2024-07-07

