SoFunction
Updated on 2025-04-20

How Java8 elegantly records code running time

In daily backend development, performance optimization is a core task. We often need to measure the execution time of a certain piece of code, such as query time, interface response time, batch task processing time, etc. In Java, the traditional approach might be to use ():

long start = ();
// Business logiclong end = ();
("Time to execute: " + (end - start) + "ms");

While this is very direct, after Java 8 introduced the package, we can achieve this with a more modern, more semantic approach - Instant and Duration.

This article will take you into the deeper understanding of several elegant ways of recording code runtime in Java 8, and will include practical tool classes and suggestions to improve your code readability and reusability.

Java 8 simple implementation

In Java 8, it represents a time point, and Duration represents the duration between two time points:

import ;
import ;

public class SampleTimer {
    public static void main(String[] args) {
        Instant start = ();

        // Simulate business logic        executeBusinessLogic();

        Instant end = ();
        long timeElapsed = (start, end).toMillis();
        ("Time to execute: " + timeElapsed + " ms");
    }

    private static void executeBusinessLogic() {
        try {
            (500); // Simulation time-consuming operation        } catch (InterruptedException e) {
            ().interrupt();
        }
    }
}

Compared with (), this writing method is more readable and expressive, and it is consistent across platforms (may be affected by system time adjustment).

Encapsulated timing tool class (more general & reusable)

To better manage runtime measurement code, we can encapsulate a small tool class, such as TimerUtils:

import ;
import ;
import ;

public class TimerUtils {

    public static <T> T measure(String taskName, Supplier<T> supplier) {
        Instant start = ();
        try {
            return ();
        } finally {
            Instant end = ();
            long duration = (start, end).toMillis();
            ("【Task: %s】Time-consuming: %d ms%n", taskName, duration);
        }
    }

    public static void measure(String taskName, Runnable runnable) {
        Instant start = ();
        try {
            ();
        } finally {
            Instant end = ();
            long duration = (start, end).toMillis();
            ("【Task: %s】Time-consuming: %d ms%n", taskName, duration);
        }
    }
}

How to use it is as follows:

public class TimerUtilsTest {
    public static void main(String[] args) {
        // No return value        ("Execute Task A", () -> {
            try {
                (200);
            } catch (InterruptedException ignored) {}
        });

        // There is a return value        String result = ("Execute Task B", () -> {
            try {
                (300);
            } catch (InterruptedException ignored) {}
            return "Task Complete";
        });

        ("Task B returns the result:" + result);
    }
}

This encapsulation method can improve the readability and reusability of the code, and is especially suitable for log output analysis in Spring Boot projects.

Advanced use: combined with log framework output

In actual projects, the recommended approach is to output time-consuming statistical information into the log to facilitate unified collection and investigation of performance bottlenecks. Combined with SLF4J + Logback, it can be integrated like this:

private static final Logger logger = ();

public void process() {
    Instant start = ();

    try {
        // Execute business logic    } finally {
        long elapsed = (start, ()).toMillis();
        ("Time-consuming to process interfaces: {} ms", elapsed);
    }
}

More professional than ELK/Prometheus and other monitoring systems to collect.

Automatically record method execution time using AOP (recommended by Spring Boot)

Performance logs can be automatically logged through Spring AOP without manually adding timing codes in each method:

1. Custom annotations:

@Target()
@Retention()
public @interface Timed {
    String value() default "";
}

2. Write facets:

@Aspect
@Component
public class TimingAspect {
    private static final Logger logger = ();

    @Around("@annotation(timed)")
    public Object around(ProceedingJoinPoint pjp, Timed timed) throws Throwable {
        Instant start = ();
        Object result = ();
        long elapsed = (start, ()).toMillis();

        String methodName = ().toShortString();
        ("method [{}] Time-consuming execution: {} ms", methodName, elapsed);
        return result;
    }
}

Example of usage:

@Timed
public void handleRequest() {
    // Logical code}

Advantages:

  • Decoupled business logic and log statistics
    • Transparent unified statistical performance data
    • Especially practical for Controller and Service layers

Other alternatives recommended

In addition to Java native classes, some open source tool classes also support efficient timing:

Guava's Stopwatch:

Stopwatch stopwatch = ();
// Execute code();
("time consuming: " + () + "ms");

Micrometer and Spring Boot Actuator provide more powerful acquisition tools for @Timed annotation and Metrics access, such as Prometheus and Grafana.

Summarize

In performance-oriented back-end development, accurately and efficiently recording code execution time is an indispensable step. This article starts with Instant/Duration native to Java 8, and demonstrates how to write more elegant, standardized, and extensible code timing.

method Elegance Reusability Recommended
generally Low
Instant + Duration good middle
Tool Packaging high high ✅✅
AOP Automated Recording Extremely high Extremely high ✅✅✅

This is the end of this article about how Java 8 elegantly records code running time. For more related content on Java 8 recording code running time, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!