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