From b43c90bd5f585e15f4aab66b29741bc06f0ea452 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=BB=84=E6=88=90=E5=85=B4?= <49221670+Createsequence@users.noreply.github.com> Date: Tue, 1 Nov 2022 18:43:49 +0800 Subject: [PATCH] refactor: Extract the logic about calculating task execution time to superclass (#879) (#882) --- .../plugin/impl/AbstractTaskTimerPlugin.java | 88 +++++++++++++++++++ .../plugin/impl/TaskTimeRecordPlugin.java | 60 ++----------- .../impl/TaskTimeoutNotifyAlarmPlugin.java | 33 ++++--- 3 files changed, 113 insertions(+), 68 deletions(-) create mode 100644 hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/AbstractTaskTimerPlugin.java diff --git a/hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/AbstractTaskTimerPlugin.java b/hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/AbstractTaskTimerPlugin.java new file mode 100644 index 00000000..4a42fef3 --- /dev/null +++ b/hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/AbstractTaskTimerPlugin.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package cn.hippo4j.core.plugin.impl; + +import cn.hippo4j.core.executor.ExtensibleThreadPoolExecutor; +import cn.hippo4j.core.plugin.ExecuteAwarePlugin; +import cn.hippo4j.core.toolkit.SystemClock; + +import java.util.Optional; + +/** + *

An abstract task execution time recording plugin + * for thread-safe statistics the execution time of tasks. + * + *

Must override {@link #processTaskTime} to define the processing logic for task execution time.
+ * Default time precision is milliseconds, may override {@link #currentTime} to redefine the time precision. + * + * @see TaskTimeRecordPlugin + * @see TaskTimeoutNotifyAlarmPlugin + */ +public abstract class AbstractTaskTimerPlugin implements ExecuteAwarePlugin { + + /** + * start times of executed tasks + */ + private final ThreadLocal startTimes = new ThreadLocal<>(); + + /** + * Record the time when the worker thread starts executing the task. + * + * @param thread thread of executing task + * @param runnable task + * @see ExtensibleThreadPoolExecutor#beforeExecute + */ + @Override + public final void beforeExecute(Thread thread, Runnable runnable) { + startTimes.set(currentTime()); + } + + /** + * Record the total time for the worker thread to complete the task, and update the time record. + * + * @param runnable runnable + * @param throwable exception thrown during execution + */ + @Override + public final void afterExecute(Runnable runnable, Throwable throwable) { + try { + Optional.ofNullable(startTimes.get()) + .map(startTime -> currentTime() - startTime) + .ifPresent(this::processTaskTime); + } finally { + startTimes.remove(); + } + } + + /** + * Get the current time. + * + * @return current time + */ + protected long currentTime() { + return SystemClock.now(); + } + + /** + * Processing the execution time of the task. + * + * @param taskExecuteTime execute time of task + */ + protected abstract void processTaskTime(long taskExecuteTime); + +} diff --git a/hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/TaskTimeRecordPlugin.java b/hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/TaskTimeRecordPlugin.java index 3ce5c5ad..0bb029c2 100644 --- a/hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/TaskTimeRecordPlugin.java +++ b/hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/TaskTimeRecordPlugin.java @@ -17,25 +17,19 @@ package cn.hippo4j.core.plugin.impl; -import cn.hippo4j.core.executor.ExtensibleThreadPoolExecutor; -import cn.hippo4j.core.plugin.ExecuteAwarePlugin; import cn.hippo4j.core.plugin.PluginRuntime; -import cn.hippo4j.core.toolkit.SystemClock; import lombok.Getter; import lombok.RequiredArgsConstructor; -import java.util.Objects; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; /** * Record task execution time indicator. - * - * @see TaskTimeoutNotifyAlarmPlugin */ @RequiredArgsConstructor -public class TaskTimeRecordPlugin implements ExecuteAwarePlugin { +public class TaskTimeRecordPlugin extends AbstractTaskTimerPlugin { public static final String PLUGIN_NAME = "task-time-record-plugin"; @@ -74,23 +68,6 @@ public class TaskTimeRecordPlugin implements ExecuteAwarePlugin { return PLUGIN_NAME; } - /** - * start times of executed tasks - */ - private final ThreadLocal startTimes = new ThreadLocal<>(); - - /** - * Record the time when the worker thread starts executing the task. - * - * @param thread thread of executing task - * @param runnable task - * @see ExtensibleThreadPoolExecutor#beforeExecute - */ - @Override - public void beforeExecute(Thread thread, Runnable runnable) { - startTimes.set(SystemClock.now()); - } - /** * Get plugin runtime info. * @@ -107,44 +84,25 @@ public class TaskTimeRecordPlugin implements ExecuteAwarePlugin { .addInfo("avgTaskTime", summary.getAvgTaskTimeMillis() + "ms"); } - /** - * Record the total time for the worker thread to complete the task, and update the time record. - * - * @param runnable runnable - * @param throwable exception thrown during execution - */ - @Override - public void afterExecute(Runnable runnable, Throwable throwable) { - try { - Long startTime = startTimes.get(); - if (Objects.isNull(startTime)) { - return; - } - long executeTime = SystemClock.now() - startTime; - recordTaskTime(executeTime); - } finally { - startTimes.remove(); - } - } - /** * Refresh time indicators of the current instance. * - * @param taskExecutionTime millisecond + * @param taskExecuteTime execute time of task */ - protected void recordTaskTime(long taskExecutionTime) { + @Override + protected void processTaskTime(long taskExecuteTime) { Lock writeLock = lock.writeLock(); writeLock.lock(); try { if (taskCount == 0) { - maxTaskTimeMillis = taskExecutionTime; - minTaskTimeMillis = taskExecutionTime; + maxTaskTimeMillis = taskExecuteTime; + minTaskTimeMillis = taskExecuteTime; } else { - maxTaskTimeMillis = Math.max(taskExecutionTime, maxTaskTimeMillis); - minTaskTimeMillis = Math.min(taskExecutionTime, minTaskTimeMillis); + maxTaskTimeMillis = Math.max(taskExecuteTime, maxTaskTimeMillis); + minTaskTimeMillis = Math.min(taskExecuteTime, minTaskTimeMillis); } taskCount = taskCount + 1; - totalTaskTimeMillis += taskExecutionTime; + totalTaskTimeMillis += taskExecuteTime; } finally { writeLock.unlock(); } diff --git a/hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/TaskTimeoutNotifyAlarmPlugin.java b/hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/TaskTimeoutNotifyAlarmPlugin.java index 12e522db..4a566f17 100644 --- a/hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/TaskTimeoutNotifyAlarmPlugin.java +++ b/hippo4j-core/src/main/java/cn/hippo4j/core/plugin/impl/TaskTimeoutNotifyAlarmPlugin.java @@ -27,11 +27,10 @@ import java.util.Optional; import java.util.concurrent.ThreadPoolExecutor; /** - * Record task execution time indicator, - * and send alarm notification when the execution time exceeds the threshold. + * Send alarm notification when the execution time exceeds the threshold. */ @AllArgsConstructor -public class TaskTimeoutNotifyAlarmPlugin extends TaskTimeRecordPlugin { +public class TaskTimeoutNotifyAlarmPlugin extends AbstractTaskTimerPlugin { public static final String PLUGIN_NAME = "task-timeout-notify-alarm-plugin"; @@ -40,6 +39,15 @@ public class TaskTimeoutNotifyAlarmPlugin extends TaskTimeRecordPlugin { */ private final String threadPoolId; + @Getter + @Setter + private Long executeTimeOut; + + /** + * thread-pool + */ + private final ThreadPoolExecutor threadPoolExecutor; + /** * Get id. * @@ -50,30 +58,21 @@ public class TaskTimeoutNotifyAlarmPlugin extends TaskTimeRecordPlugin { return PLUGIN_NAME; } - @Getter - @Setter - private Long executeTimeOut; - - /** - * thread-pool - */ - private final ThreadPoolExecutor threadPoolExecutor; - /** * Check whether the task execution time exceeds {@link #executeTimeOut}, * if it exceeds this time, send an alarm notification. * - * @param executeTime executeTime in nanosecond + * @param taskExecuteTime execute time of task */ @Override - protected void recordTaskTime(long executeTime) { - super.recordTaskTime(executeTime); - if (executeTime <= executeTimeOut) { + protected void processTaskTime(long taskExecuteTime) { + if (taskExecuteTime <= executeTimeOut) { return; } Optional.ofNullable(ApplicationContextHolder.getInstance()) .map(context -> context.getBean(ThreadPoolNotifyAlarmHandler.class)) .ifPresent(handler -> handler.asyncSendExecuteTimeOutAlarm( - threadPoolId, executeTime, executeTimeOut, threadPoolExecutor)); + threadPoolId, taskExecuteTime, executeTimeOut, threadPoolExecutor)); } + }