1, Background
sometimes we need to record the execution time of each task or the execution time of a piece of code during development. The simplest way is to print the difference between the current time and the execution completion time. Generally, we detect the execution time of a piece of code in the following way:
public static void main(String[] args) { Long startTime = System.currentTimeMillis(); // Your business code Long endTime = System.currentTimeMillis(); Long elapsedTime = (endTime - startTime) / 1000; System.out.println("Total time for this section:" + elapsedTime + "s"); } Copy code Copy code
in fact, this method obtains the execution time of the program by obtaining the difference between the execution completion time and the execution start time. It is simple, direct and effective, but it must be annoying to write too much. Especially when encountering indescribable code, people can't help writing more bug chat. Moreover, if you want to further control the execution time, It needs to be modified in many places in the program. At this time, I wonder if there is a tool class that provides these methods to meet this scenario? We can use the stopwatch in the existing tool class. The common stopwatch tool class is org springframework. util. StopWatch,org.apache.commons.lang.time.StopWatch and the stopwatch in guava provided by Google (I haven't used this much). Here we will focus on the use of spring and Apache
2, spring usage
2.1 first encounter
StopWatch is located at org springframework. A tool class under util package, which can easily time part of the program code (ms level), which is suitable for synchronizing single threaded code blocks. To sum up, the StopWatch timer provided by Spring supports the statistical output of the time characteristics of programs with seconds and milliseconds as units, especially single thread and sequential execution programs. In other words, if we have several tasks that are executed before and after in sequence, and we are more concerned about the time occupation of the execution of several tasks respectively, we hope to form a less complex log output. StopWatch provides such a function. Moreover, Spring's StopWatch is basically implemented only for such functions.
To use it, first you need to introduce the Spring core package into your Maven. Of course, Spring MVC and Spring Boot have automatically introduced the package:
<!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> Copy code Copy code
the cognition of all things starts from use. Let's take a look at its usage, as shown below:
public static void main(String[] args) throws InterruptedException { StopWatch stopWatch = new StopWatch(); // The first mock exam is dormant for 3 seconds. stopWatch.start("TaskOneName"); Thread.sleep(1000 * 3); System.out.println("Current task name:" + stopWatch.currentTaskName()); stopWatch.stop(); // The first mock exam is dormant for 10 seconds. stopWatch.start("TaskTwoName"); Thread.sleep(1000 * 10); System.out.println("Current task name:" + stopWatch.currentTaskName()); stopWatch.stop(); // The first mock exam is dormant for 10 seconds. stopWatch.start("TaskThreeName"); Thread.sleep(1000 * 10); System.out.println("Current task name:" + stopWatch.currentTaskName()); stopWatch.stop(); // Printing out takes time System.out.println(stopWatch.prettyPrint()); System.out.println(stopWatch.shortSummary()); // After stop, its value is null System.out.println(stopWatch.currentTaskName()); // Information about the last task System.out.println(stopWatch.getLastTaskName()); System.out.println(stopWatch.getLastTaskInfo()); // The total time-consuming of the task can be used if you want to get the details of each task (including its task name, time-consuming, etc.) System.out.println("Total time for all tasks:" + sw.getTotalTimeMillis()); System.out.println("Total tasks:" + sw.getTaskCount()); System.out.println("Details of all tasks:" + sw.getTaskInfo()); } Copy code Copy code
as shown in the figure, StopWatch not only correctly records the execution time of the last task, but also can give the accurate task execution time (nanosecond level) and time-consuming ratio at the end, which may be more elegant than our own output.
2.2 source code
Old rules, from shallow to deep. After reading the usage, let's take a look at the source code. First look at the properties that make up StopWatch
public class StopWatch { /** * The unique Id of this instance, which is used to distinguish between log and console output. */ private final String id; /** * Do you want to keep a taskList * Each time the timing is stopped, the current task will be put into this linked list to record the task link and timing analysis */ private boolean keepTaskList = true; /** * Task linked list * It is used to store the information of each task. taskInfo consists of taskName and totoalTime */ private final List<StopWatch.TaskInfo> taskList; /** * Start time of the current task */ private long startTimeMillis; /** * */ private boolean running; /** * Current task name */ private String currentTaskName; /** * Information for the last task */ private StopWatch.TaskInfo lastTaskInfo; /** * Total tasks */ private int taskCount; /** * Program execution time */ private long totalTimeMillis; ... } Copy code Copy code
Next, let's take a look at the constructor of the StopWatch class and some key methods
method | explain |
---|---|
new StopWatch() | Build a new stopwatch without starting any tasks. |
new StopWatch(String id) | Create a StopWatch with the specified id |
String getId() | Returns the ID of this stopwatch |
void start(String taskName) | Start the timing of an unnamed task without passing in parameters. Pass in a String type parameter to start the task timing of the specified task name |
void stop() | Stops the timing of the current task |
boolean isRunning() | Is a task being timed |
String currentTaskName() | The name of the currently running task, if any |
long getTotalTimeMillis() | Total execution time of all tasks (in milliseconds) |
double getTotalTimeSeconds() | Total time (in seconds) for all tasks |
String getLastTaskName() | The name of the previous task |
long getLastTaskTimeMillis() | Elapsed time of the previous task (in milliseconds) |
int getTaskCount() | Number of scheduled tasks |
String shortSummary() | A short description of the total run time |
String prettyPrint() | Gracefully print the detailed time consumption of all tasks |
2.3 precautions
- StopWatch objects are not designed to be thread safe and do not use synchronization.
- A StopWatch instance can only start one task at a time, and cannot start multiple tasks at the same time
- You cannot start a new task before the task has stopped. You must stop the task before you can start a new task
- To open multiple StopWatch instances at a time, you need new different StopWatch instances
3, apache usage
stopwatch is a task execution time monitor under apache commons lang3 package. It is similar to the behavior of our commonly used stopwatch. Let's take a look at some important methods first:
method | explain |
---|---|
new StopWatch() | Build a new stopwatch without starting any tasks. |
static StopWatch createStarted() | |
void start() | Start timing |
void stop() | Stops the timing of the current task |
void reset() | Reset timing |
void split() | Set split point |
void unsplit() | |
void suspend() | Pause timing until resume() is called |
void resume() | Resume timing |
long getTime() | Count the timing from start to now |
long getTime(final TimeUnit timeUnit) | |
long getNanoTime() | |
long getSplitTime() | Gets the time from start to the last split |
long getSplitNanoTime() | |
long getStartTime() | |
boolean isStarted() | |
boolean isSuspended() | |
boolean isStopped() |
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.6</version> </dependency> Copy code Copy code
the task execution monitor provided by Apache has rich functions and strong flexibility. The following classic practical cases:
public static void main(String[] args) throws InterruptedException { //start immediately after creation, commonly used StopWatch watch = StopWatch.createStarted(); // StopWatch watch = new StopWatch(); // watch.start(); Thread.sleep(1000); System.out.println(watch.getTime()); System.out.println("Statistics of running time from start to present:" + watch.getTime() + "ms"); Thread.sleep(1000); watch.split(); System.out.println("from start Time to date:" + watch.getTime()); System.out.println("Run time from start to first pointcut:" + watch.getSplitTime()); Thread.sleep(1000); watch.split(); System.out.println("Run time from start to second pointcut:" + watch.getSplitTime()); // After reset, re time watch.reset(); watch.start(); Thread.sleep(1000); System.out.println("The current running time after restart is:" + watch.getTime()); // Pause and resume watch.suspend(); System.out.println("Pause for 2 seconds"); Thread.sleep(2000); // suspend above. If you want to re count here, you need to restore it watch.resume(); System.out.println("The execution time after recovery is:" + watch.getTime()); Thread.sleep(1000); watch.stop(); System.out.println("Time spent" + watch.getTime() + "ms"); // Direct conversion to s System.out.println("Time spent" + watch.getTime(TimeUnit.SECONDS) + "s"); } Copy code Copy code
4, Finally
many times, writing code is also an art, and with the help of this practical tool, I feel more artistic. I hope we can have the heart to pursue better things, which is particularly important for accepting new knowledge. This monitor is recommended here to replace the previous use, so that partners can analyze your code more flexibly~