成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java實(shí)戰(zhàn):一行代碼搞定耗時(shí)性能追蹤

開發(fā) 前端
System.currentTimeMillis() 放在前后,相減便知道耗了多少毫秒。后來覺得這樣寫著繁瑣,且容易忘記處理異常,索性就做了這么個(gè)工具類。

前言

在開發(fā)過程中,性能監(jiān)控和調(diào)試是我們經(jīng)常面對的問題。

雖然市面上有許多成熟的性能監(jiān)控工具,但有時(shí)我們需要一個(gè)輕量級(jí)、靈活且優(yōu)雅的解決方案。

當(dāng)然也可以自己手動(dòng)在業(yè)務(wù)代碼中進(jìn)行追蹤,比如先記錄startTime,執(zhí)行結(jié)束后再拿當(dāng)前時(shí)間減去startTime,計(jì)算出耗時(shí)。

但是畢竟會(huì)制造很多重復(fù)代碼。

本文將介紹如何設(shè)計(jì)和實(shí)現(xiàn)一個(gè)簡潔而優(yōu)雅的TimeTracker工具類,它不僅能滿足基本的性能追蹤需求,還支持了函數(shù)式接口、try-with-resources等多種調(diào)用機(jī)制。

最初的痛點(diǎn)

還記得我們是怎么記錄代碼執(zhí)行時(shí)間的嗎?到處都是這樣的代碼:

long start = System.currentTimeMillis();
try {
    // 業(yè)務(wù)邏輯
} finally {
    // 計(jì)算耗時(shí)
}

每次都得寫這種重復(fù)又啰嗦的代碼,要不就得復(fù)制粘貼,還容易漏掉,CV大法固然好,但懶人總想要更懶的方式。

進(jìn)化:擁抱 try-with-resources

偶然間,我想到了 AutoCloseable 接口,再想到每次處理流的時(shí)候,直接 try 里面一包,什么都不用關(guān)心,那是不是我也可以這樣處理執(zhí)行時(shí)間?

想象一下,如果能這樣寫,那豈不是很優(yōu)雅:

try (TimeTracker ignored = new TimeTracker("數(shù)據(jù)庫操作")) {
    // 業(yè)務(wù)代碼,耗時(shí)自動(dòng)搞定!
}

瞬間,代碼變得清爽多了!資源自動(dòng)管理,耗時(shí)自動(dòng)計(jì)算,福音嘛這不是!

說干就干,新建一個(gè) TimeTracker類,實(shí)現(xiàn) AutoCloseable,簡單鼓搗一番,重點(diǎn)在于,在 close() 中計(jì)算耗時(shí),實(shí)現(xiàn)全自動(dòng)化。于是就有了第一版。

當(dāng)然,這才是剛開始。

Pro: 函數(shù)式接口

但是,還能更懶一點(diǎn)嗎?當(dāng)然可以!

不妨試試函數(shù)式接口!

比如下面這樣:

TimeTracker.track("用戶查詢", () -> {
    return userService.findById(123);
});

連 try 都不用寫了!一行代碼搞定性能監(jiān)控,是不是很???這下點(diǎn)題了不是!

什么?你說這明明是3行?

那如果我這樣寫呢?

TimeTracker.track("操作", () -> riskyMethod());

這下沒毛病了吧 ??

如果想要返回值,那也很簡單,直接這樣寫:

String result = TimeTracker.track("簡單任務(wù)", () -> {
    Thread.sleep(1000);
    return "完成";
});

和普通的調(diào)用沒有區(qū)別,毫無心智負(fù)擔(dān)。

Pro Max:異常處理

雖然現(xiàn)在一行就搞定了,但是缺少一個(gè)關(guān)鍵的功能,那就是異常處理。

考量一個(gè)程序員是否????的標(biāo)準(zhǔn),從來不是他能寫出多高大上的代碼,而且豐富的開發(fā)經(jīng)驗(yàn)和強(qiáng)大的問題追蹤能力。

因?yàn)檫@里怎么能缺少異常處理。

在上面的版本中,都沒有涉及異常,因?yàn)?.track() 內(nèi)部把異常消化掉并重新包裝成了 RuntimeException。

public static <T> T track(String operationName, ThrowableSupplier<T> execution) {
    try {
        return trackThrows(operationName, execution);
    } catch (Exception e) {
        throw new RuntimeException("執(zhí)行失敗: " + operationName, e);
    }
}

考慮到不同場景對于異常處理的需求不同,所以還得再額外提供一種模式,允許調(diào)用方顯式地進(jìn)行異常處理,把選擇權(quán)交給用戶。

比如下面這樣:

try {
    TimeTracker.trackThrows("操作", () -> {
        return riskyMethod(); // 保留原始異常
    });
} catch (SpecificException e) {
    // 精確處理
}

那這樣就大功告成了。

完整代碼

下面這是完整代碼。

各種注釋都寫在里面,可以說是非常詳細(xì)了。

包括使用示例,也寫在JavaDoc里面,真正做到注釋比代碼還多。??

/**
 * 性能跟蹤工具類,用于測量代碼執(zhí)行時(shí)間并提供靈活的異常處理機(jī)制。
 *
 * <p>主要特性:
 * <ul>
 *   <li>精確測量代碼執(zhí)行時(shí)間</li>
 *   <li>支持帶返回值和無返回值的方法跟蹤</li>
 *   <li>提供兩種異常處理模式</li>
 *   <li>支持自動(dòng)資源管理</li>
 * </ul>
 *
 * <h2>使用示例:</h2>
 *
 * <h3> try-with-resources 手動(dòng)跟蹤</h3>
 * <pre>{@code
 * // 手動(dòng)管理資源和性能跟蹤
 * try (TimeTracker tracker = new TimeTracker("數(shù)據(jù)庫操作")) {
 *     database.connect();
 *     database.executeQuery();
 * } // 自動(dòng)關(guān)閉,并打印執(zhí)行時(shí)間
 *
 * // 帶返回值的try-with-resources
 * try (TimeTracker tracker = new TimeTracker("復(fù)雜計(jì)算");
 *      Resource resource = acquireResource()) {
 *     return performComplexCalculation(resource);
 * }
 * }</pre>
 *
 * <h3>結(jié)合靜態(tài)方法的try-with-resources</h3>
 * <pre>{@code
 * try (TimeTracker ignored = TimeTracker.of("網(wǎng)絡(luò)請求")) {
 *     httpClient.sendRequest();
 *     httpClient.receiveResponse();
 * }
 * }</pre>
 *
 * <p>注意:使用try-with-resources可以確保資源正確關(guān)閉,
 * 并自動(dòng)記錄執(zhí)行時(shí)間。</p>
 *
 * <h3>lambda自動(dòng)處理異常</h3>
 * <pre>{@code
 * // 無返回值方法
 * TimeTracker.track("數(shù)據(jù)處理", () -> {
 *     processData(); // 可能拋出異常的方法
 * });
 *
 * // 有返回值方法
 * String result = TimeTracker.track("查詢用戶", () -> {
 *     return userService.findById(123);
 * });
 * }</pre>
 *
 * <h3>lambda顯式異常處理</h3>
 * <pre>{@code
 * try {
 *     // 允許拋出原始異常
 *     String result = TimeTracker.trackThrows("復(fù)雜查詢", () -> {
 *         return complexQuery(); // 可能拋出檢查異常
 *     });
 * } catch (SQLException e) {
 *     // 精確處理特定異常
 *     logger.error("數(shù)據(jù)庫查詢失敗", e);
 * }
 * }</pre>
 *
 * <h3>lambda嵌套使用</h3>
 * <pre>{@code
 * TimeTracker.track("整體流程", () -> {
 *     // 子任務(wù)1
 *     TimeTracker.track("數(shù)據(jù)準(zhǔn)備", () -> prepareData());
 *
 *     // 子任務(wù)2
 *     return TimeTracker.track("數(shù)據(jù)處理", () -> processData());
 * });
 * }</pre>
 *
 * <p>注意:默認(rèn)情況下會(huì)打印執(zhí)行時(shí)間到控制臺(tái)。對于生產(chǎn)環(huán)境,
 * 建議根據(jù)需要自定義日志記錄機(jī)制。</p>
 *
 * @author [Your Name]
 * @version 1.0
 * @since [版本號(hào)]
 */
public class TimeTracker implements AutoCloseable {
    /** 操作名稱 */
    private final String operationName;
    /** 開始時(shí)間(納秒) */
    private final long startTime;
    /** 是否啟用日志 */
    private final boolean logEnabled;

    /**
     * 創(chuàng)建一個(gè)新的TimeTracker實(shí)例。
     *
     * @param operationName 要跟蹤的操作名稱
     */
    public TimeTracker(String operationName) {
        this(operationName, true);
    }

    /**
     * 私有構(gòu)造函數(shù),用于創(chuàng)建TimeTracker實(shí)例。
     *
     * @param operationName 操作名稱
     * @param logEnabled 是否啟用日志輸出
     */
    private TimeTracker(String operationName, boolean logEnabled) {
        this.operationName = operationName;
        this.startTime = System.nanoTime();
        this.logEnabled = logEnabled;
        if (logEnabled) {
            System.out.printf("開始執(zhí)行: %s%n", operationName);
        }
    }

    /**
     * 創(chuàng)建一個(gè)新的TimeTracker實(shí)例的靜態(tài)工廠方法。
     *
     * @param operationName 要跟蹤的操作名稱
     * @return 新的TimeTracker實(shí)例
     */
    public static TimeTracker of(String operationName) {
        return new TimeTracker(operationName);
    }

    /**
     * 跟蹤帶返回值的代碼塊執(zhí)行時(shí)間,異常會(huì)被包裝為RuntimeException。
     *
     * @param operationName 操作名稱
     * @param execution 要執(zhí)行的代碼塊
     * @param <T> 返回值類型
     * @return 代碼塊的執(zhí)行結(jié)果
     * @throws RuntimeException 如果執(zhí)行過程中發(fā)生異常
     */
    public static <T> T track(String operationName, ThrowableSupplier<T> execution) {
        try {
            return trackThrows(operationName, execution);
        } catch (Exception e) {
            throw new RuntimeException("執(zhí)行失敗: " + operationName, e);
        }
    }

    /**
     * 跟蹤帶返回值的代碼塊執(zhí)行時(shí)間,允許拋出異常。
     *
     * @param operationName 操作名稱
     * @param execution 要執(zhí)行的代碼塊
     * @param <T> 返回值類型
     * @return 代碼塊的執(zhí)行結(jié)果
     * @throws Exception 如果執(zhí)行過程中發(fā)生異常
     */
    public static <T> T trackThrows(String operationName, ThrowableSupplier<T> execution) throws Exception {
        try (TimeTracker ignored = new TimeTracker(operationName, true)) {
            return execution.get();
        }
    }

    /**
     * 跟蹤無返回值的代碼塊執(zhí)行時(shí)間,異常會(huì)被包裝為RuntimeException。
     *
     * @param operationName 操作名稱
     * @param execution 要執(zhí)行的代碼塊
     * @throws RuntimeException 如果執(zhí)行過程中發(fā)生異常
     */
    public static void track(String operationName, ThrowableRunnable execution) {
        try {
            trackThrows(operationName, execution);
        } catch (Exception e) {
            throw new RuntimeException("執(zhí)行失敗: " + operationName, e);
        }
    }

    /**
     * 跟蹤無返回值的代碼塊執(zhí)行時(shí)間,允許拋出異常。
     *
     * @param operationName 操作名稱
     * @param execution 要執(zhí)行的代碼塊
     * @throws Exception 如果執(zhí)行過程中發(fā)生異常
     */
    public static void trackThrows(String operationName, ThrowableRunnable execution) throws Exception {
        try (TimeTracker ignored = new TimeTracker(operationName, true)) {
            execution.run();
        }
    }

    @Override
    public void close() {
        if (logEnabled) {
            // 計(jì)算執(zhí)行時(shí)間(轉(zhuǎn)換為毫秒)
            long timeElapsed = (System.nanoTime() - startTime) / 1_000_000;
            System.out.printf("%s 執(zhí)行完成,耗時(shí): %d ms%n", operationName, timeElapsed);
        }
    }

    /**
     * 可拋出異常的Supplier函數(shù)式接口。
     *
     * @param <T> 返回值類型
     */
    @FunctionalInterface
    public interface ThrowableSupplier<T> {
        /**
         * 獲取結(jié)果。
         *
         * @return 執(zhí)行結(jié)果
         * @throws Exception 如果執(zhí)行過程中發(fā)生錯(cuò)誤
         */
        T get() throws Exception;
    }

    /**
     * 可拋出異常的Runnable函數(shù)式接口。
     */
    @FunctionalInterface
    public interface ThrowableRunnable {
        /**
         * 執(zhí)行操作。
         *
         * @throws Exception 如果執(zhí)行過程中發(fā)生錯(cuò)誤
         */
        void run() throws Exception;
    }
}

一個(gè)DEMO

在JavaDoc里面已經(jīng)清楚寫明了調(diào)用示例,這里額外再補(bǔ)充一個(gè)Demo類,可能更清晰

import java.io.IOException;

public class TimeTrackerDemo {

    public void demonstrateUsage() {
        // 1. 使用不拋出檢查異常的版本(異常被包裝為RuntimeException)
        TimeTracker.track("簡單任務(wù)", () -> {
            Thread.sleep(1000);
            return "完成";
        });

        // 2. 使用可能拋出異常的版本
        try {
            TimeTracker.trackThrows("可能失敗的任務(wù)", () -> {
                if (Math.random() < 0.5) {
                    throw new IOException("模擬IO異常");
                }
                return "成功";
            });
        } catch (Exception e) {
            // 處理異常
            e.printStackTrace();
        }

        // 3. 嵌套使用示例
        try {
            TimeTracker.trackThrows("復(fù)雜流程", () -> {
                // 子任務(wù)1:使用不拋出異常的版本
                TimeTracker.track("子任務(wù)1", () -> {
                    Thread.sleep(500);
                });

                // 子任務(wù)2:使用拋出異常的版本
                return TimeTracker.trackThrows("子任務(wù)2", () -> {
                    Thread.sleep(500);
                    return "全部完成";
                });
            });
        } catch (Exception e) {
            // 處理異常
            e.printStackTrace();
        }

        // 4. try-with-resources 示例
        try (TimeTracker tracker = TimeTracker.of("資源管理演示")) {
            // 模擬資源操作
            performResourceIntensiveTask();
        }

        // 5. 多資源管理的try-with-resources
        try (
                TimeTracker tracker1 = TimeTracker.of("第一階段");
                TimeTracker tracker2 = TimeTracker.of("第二階段");
                // 可以同時(shí)管理其他資源
                CustomResource resource = acquireResource()
        ) {
            processResourcesSequentially(resource);
        } catch (Exception e) {
            // 異常處理
            e.printStackTrace();
        }

        // 6. 忽略返回值的try-with-resources
        try (TimeTracker ignored = TimeTracker.of("后臺(tái)任務(wù)")) {
            performBackgroundTask();
        }
    }

    // 輔助方法(僅作示例)
    private void performResourceIntensiveTask() {
        Thread.sleep(1000);
        System.out.println("資源密集型任務(wù)完成");
    }

    private CustomResource acquireResource() {
        return new CustomResource();
    }

    private void processResourcesSequentially(CustomResource resource) {
        // 處理資源的示例方法
        resource.process();
    }

    private void performBackgroundTask() {
        // 后臺(tái)任務(wù)示例
        System.out.println("執(zhí)行后臺(tái)任務(wù)");
    }

    // 模擬自定義資源類
    private static class CustomResource implements AutoCloseable {
        public void process() {
            System.out.println("處理資源");
        }

        @Override
        public void close() {
            System.out.println("關(guān)閉資源");
        }
    }
}

改進(jìn)建議

當(dāng)然,這個(gè)類還有很大的改進(jìn)空間,我簡單列幾個(gè),列位看官可以根據(jù)自己的真實(shí)場景再逐步進(jìn)行優(yōu)化。

  • 集成日志框架,比如Slf4j,支持更靈活的輸出方式
  • 添加更多的時(shí)間統(tǒng)計(jì)維度(最大值、最小值、平均值等)
  • 添加性能指標(biāo)收集,支持監(jiān)控?cái)?shù)據(jù)統(tǒng)計(jì)
  • 支持異步操作

革命尚未成功,同志仍需努力。

總結(jié)

一點(diǎn)點(diǎn)經(jīng)驗(yàn)

先來點(diǎn)經(jīng)驗(yàn)總結(jié),仁者見仁,智者見智。

  • 工具類設(shè)計(jì)務(wù)必要注重實(shí)用性和易用性的平衡
  • 工具類只是工具,千萬不能在工具類中牽扯業(yè)務(wù)
  • 異常處理需要考慮實(shí)際的真實(shí)的使用場景
  • 合理使用語言特性,可以大大簡化代碼
  • 魯棒性非常重要

寫在最后

寫代碼這些年,常常要記錄些執(zhí)行時(shí)間。起初也是簡單,System.currentTimeMillis() 放在前后,相減便知道耗了多少毫秒。后來覺得這樣寫著繁瑣,且容易忘記處理異常,索性就做了這么個(gè)工具類。

說來也沒什么新奇的,不過是用了Java里的AutoCloseable接口,再配上lambda表達(dá)式,讓代碼看起來干凈些。倒是在處理異常時(shí)費(fèi)了點(diǎn)心思,畢竟實(shí)際開發(fā)中,異常處理往往比主要邏輯還要來得復(fù)雜。

回頭再看這段代碼,倒也不覺得有多少技術(shù)含量,但確實(shí)解決了實(shí)際問題。這大概就是寫程序的意思:不是為了寫出多么驚世駭俗的代碼,而是讓原本繁瑣的事情變得簡單,讓使用者覺得舒服。

就像一把稱手的菜刀,好就好在切起菜來只覺得順手,從不會(huì)讓人去想它多么多么精妙。這個(gè)工具類也是這樣,它就在那里,不聲不響地做著它的事情。

責(zé)任編輯:武曉燕 來源: JAVA日知錄
相關(guān)推薦

2021-02-24 14:30:59

JavaScript語言開發(fā)

2024-05-31 14:04:18

2023-11-10 09:41:44

Python代碼

2024-09-18 06:10:00

條件表達(dá)式判斷代碼Python

2022-02-24 10:40:14

Python代碼

2025-04-09 11:20:00

LINQ代碼數(shù)據(jù)處理

2016-12-02 08:53:18

Python一行代碼

2025-05-09 08:00:00

JavaScript代碼防抖節(jié)流

2024-12-30 09:03:09

2021-10-29 10:38:20

代碼 PILPython

2014-02-12 13:43:50

代碼并行任務(wù)

2022-04-09 09:11:33

Python

2017-04-05 11:10:23

Javascript代碼前端

2024-12-30 08:10:00

C++17代碼文件

2021-11-11 23:02:16

電腦垃圾軟件

2025-04-27 03:00:00

Spring集成測試

2021-11-16 12:02:29

Java代碼集合

2021-08-31 09:49:37

CPU執(zhí)行語言

2017-04-13 19:20:18

Python代碼并行任務(wù)

2022-01-20 07:31:49

架構(gòu)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 91精品久久久久久久久99蜜臂 | 欧美二区三区 | 久久精品成人 | 毛片a级| 国产精彩视频 | 国产在线一区二区三区 | 久久精品亚洲精品国产欧美 | 国产一区二区精 | 成人免费视频网站在线看 | 欧美啪啪网站 | 欧美精品91 | 国产视频线观看永久免费 | 日韩一区二区三区精品 | 日韩精品视频在线免费观看 | 久久狠狠| 色久五月| 国产日韩欧美精品一区二区三区 | www.色婷婷 | 国产精品久久久久久久久久久久久 | 婷婷毛片 | 日韩精品久久久久久 | 国内精品成人 | 成人在线视频观看 | 先锋影音资源网站 | 伊人久麻豆社区 | 日日天天 | 日本久久精| 国产精品一区二区三 | 一区二区福利视频 | 欧美成人aaa级毛片在线视频 | 99免费视频 | 日韩中文字幕免费在线 | 日日夜夜精品视频 | 日韩中文字幕一区 | 精一区二区 | 精品一区二区三区视频在线观看 | 日韩高清一区 | 亚洲精品1区 | 在线播放中文 | 国产精品免费一区二区三区 | 久久亚洲精品国产精品紫薇 |