From eb3e6e7293a4967353b8c44a333414e28c073cea Mon Sep 17 00:00:00 2001 From: weihubeats Date: Sun, 30 Oct 2022 23:37:55 +0800 Subject: [PATCH 01/11] Format code (#873) * Simplified DynamicThreadPool usage * Simplified DynamicThreadPool usage * init * format code --- .../auth/filter/JWTAuthenticationFilter.java | 25 ++++++++++--------- .../config/controller/ConfigController.java | 21 ++++++++++------ 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/JWTAuthenticationFilter.java b/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/JWTAuthenticationFilter.java index 8711e89b..bf96f27f 100644 --- a/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/JWTAuthenticationFilter.java +++ b/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/JWTAuthenticationFilter.java @@ -17,6 +17,16 @@ package cn.hippo4j.auth.filter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import cn.hippo4j.auth.model.biz.user.JwtUser; import cn.hippo4j.auth.model.biz.user.LoginUser; import cn.hippo4j.auth.toolkit.JwtTokenUtil; @@ -25,6 +35,7 @@ import cn.hippo4j.common.toolkit.JSONUtil; import cn.hippo4j.common.web.base.Results; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; + import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -33,15 +44,6 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - import static cn.hippo4j.auth.constant.Constants.SPLIT_COMMA; import static cn.hippo4j.common.constant.Constants.BASE_PATH; import static cn.hippo4j.common.constant.Constants.MAP_INITIAL_CAPACITY; @@ -75,10 +77,9 @@ public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilte } catch (BadCredentialsException e) { log.warn("BadCredentialsException:{}", e.getMessage()); } catch (Exception e) { - log.error("attemptauthentication error:", e); - } finally { - return authenticate; + log.error("attemptAuthentication error:", e); } + return authenticate; } @Override diff --git a/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/controller/ConfigController.java b/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/controller/ConfigController.java index f4c48610..2011f5e8 100644 --- a/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/controller/ConfigController.java +++ b/hippo4j-server/hippo4j-config/src/main/java/cn/hippo4j/config/controller/ConfigController.java @@ -17,6 +17,12 @@ package cn.hippo4j.config.controller; +import java.net.URLDecoder; +import java.util.Map; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + import cn.hippo4j.common.constant.ConfigModifyTypeConstants; import cn.hippo4j.common.constant.Constants; import cn.hippo4j.common.model.register.DynamicThreadPoolRegisterWrapper; @@ -35,13 +41,14 @@ import cn.hippo4j.config.toolkit.Md5ConfigUtil; import cn.hippo4j.config.verify.ConfigModificationVerifyServiceChoose; import lombok.AllArgsConstructor; import lombok.SneakyThrows; -import org.springframework.util.StringUtils; -import org.springframework.web.bind.annotation.*; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import java.net.URLDecoder; -import java.util.Map; +import org.springframework.util.StringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; /** * Server configuration controller. @@ -76,7 +83,7 @@ public class ConfigController { modifySaveReqDTO.setCorePoolSize(config.getCoreSize()); modifySaveReqDTO.setMaximumPoolSize(config.getMaxSize()); modifySaveReqDTO.setModifyUser(UserContext.getUserName()); - modifySaveReqDTO.setModifyAll(StringUtil.isEmpty(identify) ? true : false); + modifySaveReqDTO.setModifyAll(StringUtil.isEmpty(identify)); modifySaveReqDTO.setIdentify(identify); modifySaveReqDTO.setType(ConfigModifyTypeConstants.THREAD_POOL_INSTANCE); configModificationVerifyServiceChoose.choose(modifySaveReqDTO.getType()).saveConfigModifyApplication(modifySaveReqDTO); From 233ebeef28a51ecc5c5e0b95c1f2f62cac5a2c32 Mon Sep 17 00:00:00 2001 From: "chen.ma" Date: Sun, 30 Oct 2022 23:47:28 +0800 Subject: [PATCH 02/11] Optimize code exception information --- .../auth/filter/JWTAuthenticationFilter.java | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/JWTAuthenticationFilter.java b/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/JWTAuthenticationFilter.java index bf96f27f..f77f579a 100644 --- a/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/JWTAuthenticationFilter.java +++ b/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/JWTAuthenticationFilter.java @@ -17,16 +17,6 @@ package cn.hippo4j.auth.filter; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -import javax.servlet.FilterChain; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - import cn.hippo4j.auth.model.biz.user.JwtUser; import cn.hippo4j.auth.model.biz.user.LoginUser; import cn.hippo4j.auth.toolkit.JwtTokenUtil; @@ -35,7 +25,6 @@ import cn.hippo4j.common.toolkit.JSONUtil; import cn.hippo4j.common.web.base.Results; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; - import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -44,6 +33,15 @@ import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import javax.servlet.FilterChain; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + import static cn.hippo4j.auth.constant.Constants.SPLIT_COMMA; import static cn.hippo4j.common.constant.Constants.BASE_PATH; import static cn.hippo4j.common.constant.Constants.MAP_INITIAL_CAPACITY; @@ -75,9 +73,9 @@ public class JWTAuthenticationFilter extends UsernamePasswordAuthenticationFilte authenticate = authenticationManager.authenticate( new UsernamePasswordAuthenticationToken(loginUser.getUsername(), loginUser.getPassword(), new ArrayList())); } catch (BadCredentialsException e) { - log.warn("BadCredentialsException:{}", e.getMessage()); + log.warn("Bad credentials exception: {}", e.getMessage()); } catch (Exception e) { - log.error("attemptAuthentication error:", e); + log.error("Attempt authentication error", e); } return authenticate; } From a1938696194a5134b07f60f9965fc9a4a054d673 Mon Sep 17 00:00:00 2001 From: "chen.ma" Date: Mon, 31 Oct 2022 12:26:38 +0800 Subject: [PATCH 03/11] Increase unit test code coverage --- .codecov.yml | 2 +- .../auth/filter/RewriteUserInfoApiFilter.java | 2 +- .../cn/hippo4j/auth/toolkit/AuthUtil.java | 10 +++- .../cn/hippo4j/auth/toolkit/AuthUtilTest.java | 38 ++++++++++++++ .../cn/hippo4j/auth/toolkit/ReturnTTest.java | 49 +++++++++++++++++++ 5 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 hippo4j-server/hippo4j-auth/src/test/java/cn/hippo4j/auth/toolkit/AuthUtilTest.java create mode 100644 hippo4j-server/hippo4j-auth/src/test/java/cn/hippo4j/auth/toolkit/ReturnTTest.java diff --git a/.codecov.yml b/.codecov.yml index a6ffc2d4..ab1c78cb 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -19,7 +19,7 @@ coverage: status: patch: default: - threshold: 0.1% + threshold: 0.01% ignore: - "hippo4j-example/.*" - "docs/.*" diff --git a/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/RewriteUserInfoApiFilter.java b/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/RewriteUserInfoApiFilter.java index 8e789d30..8144f7bc 100644 --- a/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/RewriteUserInfoApiFilter.java +++ b/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/filter/RewriteUserInfoApiFilter.java @@ -34,7 +34,7 @@ public class RewriteUserInfoApiFilter implements Filter { @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { - boolean enableAuthentication = AuthUtil.enableAuthentication; + boolean enableAuthentication = AuthUtil.ENABLE_AUTHENTICATION; HttpServletRequest httpRequest = (HttpServletRequest) servletRequest; String path = httpRequest.getRequestURI(); if (!enableAuthentication && path.contains("users/info")) { diff --git a/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/toolkit/AuthUtil.java b/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/toolkit/AuthUtil.java index ab6f9b9a..62e0371f 100644 --- a/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/toolkit/AuthUtil.java +++ b/hippo4j-server/hippo4j-auth/src/main/java/cn/hippo4j/auth/toolkit/AuthUtil.java @@ -20,13 +20,19 @@ package cn.hippo4j.auth.toolkit; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +/** + * Auth util. + */ @Component public class AuthUtil { - public static boolean enableAuthentication; + /** + * Enable authentication + */ + public static boolean ENABLE_AUTHENTICATION; @Value("${hippo4j.core.auth.enabled:true}") public void setEnableAuthentication(boolean enabled) { - AuthUtil.enableAuthentication = enabled; + AuthUtil.ENABLE_AUTHENTICATION = enabled; } } \ No newline at end of file diff --git a/hippo4j-server/hippo4j-auth/src/test/java/cn/hippo4j/auth/toolkit/AuthUtilTest.java b/hippo4j-server/hippo4j-auth/src/test/java/cn/hippo4j/auth/toolkit/AuthUtilTest.java new file mode 100644 index 00000000..dd522658 --- /dev/null +++ b/hippo4j-server/hippo4j-auth/src/test/java/cn/hippo4j/auth/toolkit/AuthUtilTest.java @@ -0,0 +1,38 @@ +/* + * 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.auth.toolkit; + +import cn.hippo4j.common.toolkit.Assert; +import org.junit.Before; +import org.junit.Test; + +public final class AuthUtilTest { + + private AuthUtil authUtil; + + @Before + public void beforeInit() { + authUtil = new AuthUtil(); + authUtil.setEnableAuthentication(true); + } + + @Test + public void assertGetEnableAuthentication() { + Assert.isTrue(AuthUtil.ENABLE_AUTHENTICATION); + } +} diff --git a/hippo4j-server/hippo4j-auth/src/test/java/cn/hippo4j/auth/toolkit/ReturnTTest.java b/hippo4j-server/hippo4j-auth/src/test/java/cn/hippo4j/auth/toolkit/ReturnTTest.java new file mode 100644 index 00000000..8c2ff9b2 --- /dev/null +++ b/hippo4j-server/hippo4j-auth/src/test/java/cn/hippo4j/auth/toolkit/ReturnTTest.java @@ -0,0 +1,49 @@ +/* + * 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.auth.toolkit; + +import cn.hippo4j.common.toolkit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.Objects; + +public final class ReturnTTest { + + private ReturnT returnT; + + @Before + public void beforeInit() { + returnT = new ReturnT("success"); + } + + @Test + public void assertGetCode() { + Assert.isTrue(Objects.equals(returnT.getCode(), 200)); + } + + @Test + public void assertGetMessage() { + Assert.isNull(returnT.getMsg()); + } + + @Test + public void assertGetContent() { + Assert.isTrue(Objects.equals(returnT.getContent(), "success")); + } +} From e64493bbce309030fe01c2957d62f91748b4ccab Mon Sep 17 00:00:00 2001 From: WuLang <48200100+wulangcode@users.noreply.github.com> Date: Mon, 31 Oct 2022 21:43:28 +0800 Subject: [PATCH 04/11] feat:Alarm content (#877) --- .../resources/message/robot/dynamic-thread-pool/ding-alarm.txt | 2 +- .../resources/message/robot/dynamic-thread-pool/lark-alarm.json | 2 +- .../message/robot/dynamic-thread-pool/wechat-alarm.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/ding-alarm.txt b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/ding-alarm.txt index 55064be3..7fda29d7 100644 --- a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/ding-alarm.txt +++ b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/ding-alarm.txt @@ -1,4 +1,4 @@ -**[警报] %s - 动态线程池运行告警(%s)** +**[告警] %s - 动态线程池运行告警(%s)** --- diff --git a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm.json b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm.json index 0e451e93..2bc88c3a 100644 --- a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm.json +++ b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/lark-alarm.json @@ -7,7 +7,7 @@ "header": { "template": "red", "title": { - "content": "[🔥警报] %s 动态线程池运行告警(%s)", + "content": "[🔥告警] %s 动态线程池运行告警(%s)", "tag": "plain_text" } }, diff --git a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/wechat-alarm.txt b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/wechat-alarm.txt index 56f7ace1..00dd33b2 100644 --- a/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/wechat-alarm.txt +++ b/hippo4j-message/src/main/resources/message/robot/dynamic-thread-pool/wechat-alarm.txt @@ -1,4 +1,4 @@ -### [警报] %s - 动态线程池运行告警(%s) +### [告警] %s - 动态线程池运行告警(%s) > 线程池ID:%s > 应用名称:%s From fd0297ee4edc43f3c5d3f775548361b51df3ac83 Mon Sep 17 00:00:00 2001 From: "chen.ma" Date: Mon, 31 Oct 2022 21:48:06 +0800 Subject: [PATCH 05/11] In version 1.4.3, the DingTalk alarm keyword was modified (#869) --- docs/docs/user_docs/user_guide/notify.md | 5 ++++- .../current/user_docs/user_guide/notify.md | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/docs/user_docs/user_guide/notify.md b/docs/docs/user_docs/user_guide/notify.md index 216840e9..924d5a7e 100644 --- a/docs/docs/user_docs/user_guide/notify.md +++ b/docs/docs/user_docs/user_guide/notify.md @@ -41,7 +41,6 @@ WECHART:填写user_id会以@的消息发给用户,填写姓名则是普通 LARK:填写ou_开头用户唯一标识会以@的消息发给用户,填写手机号则是普通的@ ``` - ## 钉钉平台 [钉钉创建群机器人](https://www.dingtalk.com/qidian/help-detail-20781541.html) @@ -54,6 +53,10 @@ LARK:填写ou_开头用户唯一标识会以@的消息发给用户,填写手 ![](https://images-machen.oss-cn-beijing.aliyuncs.com/image-20220530200133377.png?x-oss-process=image/resize,h_500,w_800) +:::tip +如果使用 1.4.3 及以上版本,`警报` 替换为 `告警`。 +::: + ## 企业微信 [企业微信创建群机器人](https://open.work.weixin.qq.com/help2/pc/14931?person_id=1&from=homesearch) diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/current/user_docs/user_guide/notify.md b/docs/i18n/zh/docusaurus-plugin-content-docs/current/user_docs/user_guide/notify.md index 216840e9..d4ca2bfd 100644 --- a/docs/i18n/zh/docusaurus-plugin-content-docs/current/user_docs/user_guide/notify.md +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/current/user_docs/user_guide/notify.md @@ -54,6 +54,10 @@ LARK:填写ou_开头用户唯一标识会以@的消息发给用户,填写手 ![](https://images-machen.oss-cn-beijing.aliyuncs.com/image-20220530200133377.png?x-oss-process=image/resize,h_500,w_800) +:::tip +如果使用 1.4.3 及以上版本,`警报` 替换为 `告警`。 +::: + ## 企业微信 [企业微信创建群机器人](https://open.work.weixin.qq.com/help2/pc/14931?person_id=1&from=homesearch) From cc52829e24e675f2d09b639b0f94d51d10bfd2c6 Mon Sep 17 00:00:00 2001 From: "chen.ma" Date: Mon, 31 Oct 2022 23:43:21 +0800 Subject: [PATCH 06/11] Add registered company --- docs/docs/community/powered-by.md | 3 ++- .../current/community/powered-by.md | 3 ++- .../version-1.4.2/community/powered-by.md | 3 ++- docs/versioned_docs/version-1.4.2/community/powered-by.md | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/docs/community/powered-by.md b/docs/docs/community/powered-by.md index 81bf0e32..635d9011 100644 --- a/docs/docs/community/powered-by.md +++ b/docs/docs/community/powered-by.md @@ -12,7 +12,7 @@ sidebar_position: 3 ## 谁在使用 Hippo4J -共计 20+ 家公司生产接入 Hippo4J。按照公司登记时间排序。 +共计 21+ 家公司生产接入 Hippo4J。按照公司登记时间排序。 - [身边云](https://serviceshare.com) - [Medbanks](https://www.medbanks.cn) @@ -34,3 +34,4 @@ sidebar_position: 3 - [新东方教育科技集团](https://www.xdf.cn/) - [远眺网络科技有限公司](https://www.yuantiaokj.com/) - [浙江吉利控股集团有限公司](https://www.geely.com/) +- [三立人(深圳)科技有限公司-焦内](https://www.bananain.com/) diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/current/community/powered-by.md b/docs/i18n/zh/docusaurus-plugin-content-docs/current/community/powered-by.md index 81bf0e32..635d9011 100644 --- a/docs/i18n/zh/docusaurus-plugin-content-docs/current/community/powered-by.md +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/current/community/powered-by.md @@ -12,7 +12,7 @@ sidebar_position: 3 ## 谁在使用 Hippo4J -共计 20+ 家公司生产接入 Hippo4J。按照公司登记时间排序。 +共计 21+ 家公司生产接入 Hippo4J。按照公司登记时间排序。 - [身边云](https://serviceshare.com) - [Medbanks](https://www.medbanks.cn) @@ -34,3 +34,4 @@ sidebar_position: 3 - [新东方教育科技集团](https://www.xdf.cn/) - [远眺网络科技有限公司](https://www.yuantiaokj.com/) - [浙江吉利控股集团有限公司](https://www.geely.com/) +- [三立人(深圳)科技有限公司-焦内](https://www.bananain.com/) diff --git a/docs/i18n/zh/docusaurus-plugin-content-docs/version-1.4.2/community/powered-by.md b/docs/i18n/zh/docusaurus-plugin-content-docs/version-1.4.2/community/powered-by.md index 81bf0e32..635d9011 100644 --- a/docs/i18n/zh/docusaurus-plugin-content-docs/version-1.4.2/community/powered-by.md +++ b/docs/i18n/zh/docusaurus-plugin-content-docs/version-1.4.2/community/powered-by.md @@ -12,7 +12,7 @@ sidebar_position: 3 ## 谁在使用 Hippo4J -共计 20+ 家公司生产接入 Hippo4J。按照公司登记时间排序。 +共计 21+ 家公司生产接入 Hippo4J。按照公司登记时间排序。 - [身边云](https://serviceshare.com) - [Medbanks](https://www.medbanks.cn) @@ -34,3 +34,4 @@ sidebar_position: 3 - [新东方教育科技集团](https://www.xdf.cn/) - [远眺网络科技有限公司](https://www.yuantiaokj.com/) - [浙江吉利控股集团有限公司](https://www.geely.com/) +- [三立人(深圳)科技有限公司-焦内](https://www.bananain.com/) diff --git a/docs/versioned_docs/version-1.4.2/community/powered-by.md b/docs/versioned_docs/version-1.4.2/community/powered-by.md index 81bf0e32..635d9011 100644 --- a/docs/versioned_docs/version-1.4.2/community/powered-by.md +++ b/docs/versioned_docs/version-1.4.2/community/powered-by.md @@ -12,7 +12,7 @@ sidebar_position: 3 ## 谁在使用 Hippo4J -共计 20+ 家公司生产接入 Hippo4J。按照公司登记时间排序。 +共计 21+ 家公司生产接入 Hippo4J。按照公司登记时间排序。 - [身边云](https://serviceshare.com) - [Medbanks](https://www.medbanks.cn) @@ -34,3 +34,4 @@ sidebar_position: 3 - [新东方教育科技集团](https://www.xdf.cn/) - [远眺网络科技有限公司](https://www.yuantiaokj.com/) - [浙江吉利控股集团有限公司](https://www.geely.com/) +- [三立人(深圳)科技有限公司-焦内](https://www.bananain.com/) From 175bfb9c54dbd842ff3f54cb87d9c35b40afe774 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:02 +0800 Subject: [PATCH 07/11] test: Add unit test for DynamicThreadPoolExecutor and ExtensibleThreadPoolExecutor (#884) --- hippo4j-core/pom.xml | 5 + .../DynamicThreadPoolExecutorTest.java | 158 +++++++++++++ .../ExtensibleThreadPoolExecutorTest.java | 219 ++++++++++++++++++ 3 files changed, 382 insertions(+) create mode 100644 hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java create mode 100644 hippo4j-core/src/test/java/cn/hippo4j/core/executor/ExtensibleThreadPoolExecutorTest.java diff --git a/hippo4j-core/pom.xml b/hippo4j-core/pom.xml index bd891a49..e9e05f10 100644 --- a/hippo4j-core/pom.xml +++ b/hippo4j-core/pom.xml @@ -10,6 +10,11 @@ hippo4j-core + + org.springframework.boot + spring-boot-starter-test + test + org.projectlombok lombok diff --git a/hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java b/hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java new file mode 100644 index 00000000..cfa344a0 --- /dev/null +++ b/hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java @@ -0,0 +1,158 @@ +/* + * 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.executor; + +import cn.hippo4j.common.toolkit.ThreadUtil; +import org.junit.Assert; +import org.junit.Test; +import org.springframework.core.task.TaskDecorator; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * test for {@link DynamicThreadPoolExecutor} + */ +public class DynamicThreadPoolExecutorTest { + + @Test + public void testRedundancyHandler() { + RejectedExecutionHandler handler = new ThreadPoolExecutor.DiscardOldestPolicy(); + + DynamicThreadPoolExecutor executor = new DynamicThreadPoolExecutor( + 1, 1, 1000L, TimeUnit.MILLISECONDS, + 1000L, true, 1000L, + new ArrayBlockingQueue<>(1), "test", Thread::new, handler); + + Assert.assertEquals(handler, executor.getRedundancyHandler()); + handler = new ThreadPoolExecutor.AbortPolicy(); + executor.setRedundancyHandler(handler); + Assert.assertEquals(handler, executor.getRedundancyHandler()); + } + + @Test + public void testTaskDecorator() { + DynamicThreadPoolExecutor executor = new DynamicThreadPoolExecutor( + 1, 1, 1000L, TimeUnit.MILLISECONDS, + 1000L, true, 1000L, + new ArrayBlockingQueue<>(1), "test", Thread::new, new ThreadPoolExecutor.DiscardOldestPolicy()); + + Assert.assertNull(executor.getTaskDecorator()); + TaskDecorator decorator = runnable -> runnable; + executor.setTaskDecorator(decorator); + Assert.assertEquals(decorator, executor.getTaskDecorator()); + + decorator = runnable -> runnable; + executor.setTaskDecorator(decorator); + Assert.assertEquals(decorator, executor.getTaskDecorator()); + } + + @Test + public void testExecuteTimeOut() { + DynamicThreadPoolExecutor executor = new DynamicThreadPoolExecutor( + 1, 1, 1000L, TimeUnit.MILLISECONDS, + 1000L, true, 1000L, + new ArrayBlockingQueue<>(1), "test", Thread::new, new ThreadPoolExecutor.DiscardOldestPolicy()); + + Assert.assertEquals(1000L, executor.getExecuteTimeOut().longValue()); + executor.setExecuteTimeOut(500L); + Assert.assertEquals(500L, executor.getExecuteTimeOut().longValue()); + } + + @Test + public void testDestroyWhenWaitForTask() { + DynamicThreadPoolExecutor executor = new DynamicThreadPoolExecutor( + 1, 1, 1000L, TimeUnit.MILLISECONDS, + 1000L, true, 1000L, + new ArrayBlockingQueue<>(1), "test", Thread::new, new ThreadPoolExecutor.DiscardOldestPolicy()); + AtomicInteger count = new AtomicInteger(0); + + executor.execute(() -> { + ThreadUtil.sleep(500L); + count.incrementAndGet(); + }); + executor.execute(() -> { + ThreadUtil.sleep(500L); + count.incrementAndGet(); + }); + executor.destroy(); + + // waitting for terminated + while (!executor.isTerminated()){}; + Assert.assertEquals(2, count.get()); + } + + @Test + public void testDestroyWhenNotWaitForTask() { + DynamicThreadPoolExecutor executor = new DynamicThreadPoolExecutor( + 1, 1, 1000L, TimeUnit.MILLISECONDS, + 1000L, false, 1000L, + new ArrayBlockingQueue<>(1), "test", Thread::new, new ThreadPoolExecutor.DiscardOldestPolicy()); + AtomicInteger count = new AtomicInteger(0); + + executor.execute(() -> { + ThreadUtil.sleep(500L); + count.incrementAndGet(); + }); + executor.execute(() -> { + ThreadUtil.sleep(500L); + count.incrementAndGet(); + }); + executor.destroy(); + + // waitting for terminated + while (!executor.isTerminated()){}; + Assert.assertEquals(1, count.get()); + } + + @Test + public void testRejectCount() { + DynamicThreadPoolExecutor executor = new DynamicThreadPoolExecutor( + 1, 1, 1000L, TimeUnit.MILLISECONDS, + 1000L, true, 1000L, + new ArrayBlockingQueue<>(1), "test", Thread::new, new ThreadPoolExecutor.DiscardOldestPolicy()); + + Assert.assertEquals(0L, executor.getRejectCountNum().longValue()); + Assert.assertEquals(0L, executor.getRejectCount().get()); + + executor.submit(() -> ThreadUtil.sleep(100L)); + executor.submit(() -> ThreadUtil.sleep(100L)); + executor.submit(() -> ThreadUtil.sleep(100L)); + ThreadUtil.sleep(200L); + Assert.assertEquals(1L, executor.getRejectCountNum().longValue()); + Assert.assertEquals(1L, executor.getRejectCount().get()); + } + + @Test + public void testSupportParam() { + DynamicThreadPoolExecutor executor = new DynamicThreadPoolExecutor( + 1, 1, 1000L, TimeUnit.MILLISECONDS, + 1000L, true, 1000L, + new ArrayBlockingQueue<>(1), "test", Thread::new, new ThreadPoolExecutor.DiscardOldestPolicy()); + Assert.assertEquals(1000L, executor.getAwaitTerminationMillis()); + Assert.assertTrue(executor.isWaitForTasksToCompleteOnShutdown()); + + executor.setSupportParam(500L, false); + Assert.assertEquals(500L, executor.getAwaitTerminationMillis()); + Assert.assertFalse(executor.isWaitForTasksToCompleteOnShutdown()); + } + +} diff --git a/hippo4j-core/src/test/java/cn/hippo4j/core/executor/ExtensibleThreadPoolExecutorTest.java b/hippo4j-core/src/test/java/cn/hippo4j/core/executor/ExtensibleThreadPoolExecutorTest.java new file mode 100644 index 00000000..7642adc6 --- /dev/null +++ b/hippo4j-core/src/test/java/cn/hippo4j/core/executor/ExtensibleThreadPoolExecutorTest.java @@ -0,0 +1,219 @@ +/* + * 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.executor; + +import cn.hippo4j.common.toolkit.ThreadUtil; +import cn.hippo4j.core.plugin.ExecuteAwarePlugin; +import cn.hippo4j.core.plugin.RejectedAwarePlugin; +import cn.hippo4j.core.plugin.ShutdownAwarePlugin; +import cn.hippo4j.core.plugin.TaskAwarePlugin; +import cn.hippo4j.core.plugin.manager.DefaultThreadPoolPluginManager; +import cn.hippo4j.core.plugin.manager.ThreadPoolPluginManager; +import lombok.Getter; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.List; +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * test for {@link ExtensibleThreadPoolExecutor} + */ +public class ExtensibleThreadPoolExecutorTest { + + private final RejectedExecutionHandler originalHandler = new ThreadPoolExecutor.DiscardPolicy(); + + private ExtensibleThreadPoolExecutor executor; + + private ThreadPoolPluginManager manager; + + @Before + public void initExecutor() { + manager = new DefaultThreadPoolPluginManager(); + executor = new ExtensibleThreadPoolExecutor( + "test", manager, + 5, 5, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(1), Thread::new, originalHandler); + } + + @Test + public void testGetThreadPoolId() { + Assert.assertEquals("test", executor.getThreadPoolId()); + } + + @Test + public void testGetThreadPoolExecutor() { + Assert.assertSame(executor, executor.getThreadPoolExecutor()); + } + + @Test + public void testGetThreadPoolPluginManager() { + Assert.assertSame(manager, executor.getThreadPoolPluginManager()); + } + + @Test + public void testGetOrSetRejectedHandler() { + RejectedExecutionHandler handler = new ThreadPoolExecutor.AbortPolicy(); + executor.setRejectedExecutionHandler(handler); + Assert.assertSame(handler, executor.getRejectedExecutionHandler()); + } + + @Test + public void testInvokeTaskAwarePlugin() { + TestTaskAwarePlugin plugin = new TestTaskAwarePlugin(); + executor.register(plugin); + executor.submit(() -> { + }); + executor.submit(() -> true); + executor.submit(() -> { + }, false); + executor.execute(() -> { + }); + Assert.assertEquals(7, plugin.getInvokeCount().get()); + } + + @Test + public void testInvokeExecuteAwarePlugin() { + TestExecuteAwarePlugin plugin = new TestExecuteAwarePlugin(); + executor.register(plugin); + executor.execute(() -> { + }); + ThreadUtil.sleep(500L); + Assert.assertEquals(2, plugin.getInvokeCount().get()); + } + + @Test + public void testInvokeRejectedAwarePlugin() { + executor.setCorePoolSize(1); + executor.setMaximumPoolSize(1); + + TestRejectedAwarePlugin plugin = new TestRejectedAwarePlugin(); + executor.register(plugin); + // blocking pool and queue + executor.submit(() -> ThreadUtil.sleep(500L)); + executor.submit(() -> ThreadUtil.sleep(500L)); + // reject 3 tasks + executor.submit(() -> { + }); + executor.submit(() -> { + }); + executor.submit(() -> { + }); + + ThreadUtil.sleep(500L); + Assert.assertEquals(3, plugin.getInvokeCount().get()); + } + + @Test + public void testInvokeTestShutdownAwarePluginWhenShutdown() throws InterruptedException { + TestShutdownAwarePlugin plugin = new TestShutdownAwarePlugin(); + executor.register(plugin); + executor.shutdown(); + executor.submit(() -> { + throw new IllegalArgumentException("???"); + }); + if (executor.awaitTermination(500L, TimeUnit.MILLISECONDS)) { + Assert.assertEquals(3, plugin.getInvokeCount().get()); + } + } + + @Test + public void testInvokeTestShutdownAwarePluginWhenShutdownNow() throws InterruptedException { + TestShutdownAwarePlugin plugin = new TestShutdownAwarePlugin(); + executor.register(plugin); + executor.shutdownNow(); + if (executor.awaitTermination(500L, TimeUnit.MILLISECONDS)) { + Assert.assertEquals(3, plugin.getInvokeCount().get()); + } + } + + @Getter + private final static class TestTaskAwarePlugin implements TaskAwarePlugin { + + private final AtomicInteger invokeCount = new AtomicInteger(0); + private final String id = "TestTaskAwarePlugin"; + @Override + public Runnable beforeTaskCreate(ThreadPoolExecutor executor, Runnable runnable, V value) { + invokeCount.incrementAndGet(); + return TaskAwarePlugin.super.beforeTaskCreate(executor, runnable, value); + } + @Override + public Callable beforeTaskCreate(ThreadPoolExecutor executor, Callable future) { + invokeCount.incrementAndGet(); + return TaskAwarePlugin.super.beforeTaskCreate(executor, future); + } + @Override + public Runnable beforeTaskExecute(Runnable runnable) { + invokeCount.incrementAndGet(); + return TaskAwarePlugin.super.beforeTaskExecute(runnable); + } + } + + @Getter + private final static class TestExecuteAwarePlugin implements ExecuteAwarePlugin { + + private final AtomicInteger invokeCount = new AtomicInteger(0); + private final String id = "TestExecuteAwarePlugin"; + @Override + public void beforeExecute(Thread thread, Runnable runnable) { + invokeCount.incrementAndGet(); + ExecuteAwarePlugin.super.beforeExecute(thread, runnable); + } + @Override + public void afterExecute(Runnable runnable, Throwable throwable) { + invokeCount.incrementAndGet(); + ExecuteAwarePlugin.super.afterExecute(runnable, throwable); + } + } + + @Getter + private final static class TestRejectedAwarePlugin implements RejectedAwarePlugin { + + private final AtomicInteger invokeCount = new AtomicInteger(0); + private final String id = "TestRejectedAwarePlugin"; + @Override + public void beforeRejectedExecution(Runnable runnable, ThreadPoolExecutor executor) { + invokeCount.incrementAndGet(); + } + } + + @Getter + private final static class TestShutdownAwarePlugin implements ShutdownAwarePlugin { + + private final AtomicInteger invokeCount = new AtomicInteger(0); + private final String id = "TestShutdownAwarePlugin"; + @Override + public void beforeShutdown(ThreadPoolExecutor executor) { + invokeCount.incrementAndGet(); + ShutdownAwarePlugin.super.beforeShutdown(executor); + } + @Override + public void afterShutdown(ThreadPoolExecutor executor, List remainingTasks) { + invokeCount.incrementAndGet(); + ShutdownAwarePlugin.super.afterShutdown(executor, remainingTasks); + } + @Override + public void afterTerminated(ExtensibleThreadPoolExecutor executor) { + invokeCount.incrementAndGet(); + ShutdownAwarePlugin.super.afterTerminated(executor); + } + } + +} 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 08/11] 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)); } + } From 0f2f7a9be43c4c443f27708a6dc027a934c7bc2f 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 19:01:18 +0800 Subject: [PATCH 09/11] test: Add benchmark test for TaskTimeRecord (#885) --- hippo4j-example/hippo4j-example-core/pom.xml | 15 ++ .../TaskTimeRecordPluginBenchmarkTest.java | 151 ++++++++++++++++++ 2 files changed, 166 insertions(+) create mode 100644 hippo4j-example/hippo4j-example-core/src/test/java/cn/hippo4j/example/core/TaskTimeRecordPluginBenchmarkTest.java diff --git a/hippo4j-example/hippo4j-example-core/pom.xml b/hippo4j-example/hippo4j-example-core/pom.xml index 50ed2a3d..2628dbd6 100644 --- a/hippo4j-example/hippo4j-example-core/pom.xml +++ b/hippo4j-example/hippo4j-example-core/pom.xml @@ -34,5 +34,20 @@ com.alibaba transmittable-thread-local + + + org.openjdk.jmh + jmh-core + 1.23 + test + + + + org.openjdk.jmh + jmh-generator-annprocess + 1.23 + test + + diff --git a/hippo4j-example/hippo4j-example-core/src/test/java/cn/hippo4j/example/core/TaskTimeRecordPluginBenchmarkTest.java b/hippo4j-example/hippo4j-example-core/src/test/java/cn/hippo4j/example/core/TaskTimeRecordPluginBenchmarkTest.java new file mode 100644 index 00000000..2bf935a4 --- /dev/null +++ b/hippo4j-example/hippo4j-example-core/src/test/java/cn/hippo4j/example/core/TaskTimeRecordPluginBenchmarkTest.java @@ -0,0 +1,151 @@ +package cn.hippo4j.example.core; + +import cn.hippo4j.core.executor.ExtensibleThreadPoolExecutor; +import cn.hippo4j.core.plugin.impl.TaskTimeRecordPlugin; +import cn.hippo4j.core.plugin.manager.DefaultThreadPoolPluginManager; +import lombok.SneakyThrows; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; +import org.openjdk.jmh.results.format.ResultFormatType; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * benchmark test for {@link cn.hippo4j.core.plugin.impl.TaskTimeRecordPlugin} + */ +@BenchmarkMode(Mode.All) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@State(Scope.Thread) +@Warmup(iterations = 1) +@Measurement(iterations = 3) +@Fork(1) +@Threads(6) +public class TaskTimeRecordPluginBenchmarkTest { + + @SneakyThrows + @Benchmark + public void origin_200(Blackhole blackhole) { + int threadCount = 200; + ThreadPoolExecutor executor = new ThreadPoolExecutor( + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + executor.prestartAllCoreThreads(); + + List tasks = getTask(threadCount, blackhole); + tasks.forEach(executor::execute); + + executor.shutdown(); + while (!executor.isTerminated()) {} + } + + @SneakyThrows + @Benchmark + public void origin_50(Blackhole blackhole) { + int threadCount = 50; + ThreadPoolExecutor executor = new ThreadPoolExecutor( + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + executor.prestartAllCoreThreads(); + + List tasks = getTask(threadCount, blackhole); + tasks.forEach(executor::execute); + + executor.shutdown(); + while (!executor.isTerminated()) {} + } + + @SneakyThrows + @Benchmark + public void not_plugin_50(Blackhole blackhole) { + int threadCount = 50; + ExtensibleThreadPoolExecutor executor = new ExtensibleThreadPoolExecutor( + "test", new DefaultThreadPoolPluginManager(), + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + executor.prestartAllCoreThreads(); + + List tasks = getTask(threadCount, blackhole); + tasks.forEach(executor::execute); + + executor.shutdown(); + while (!executor.isTerminated()) {} + } + + @SneakyThrows + @Benchmark + public void not_plugin_200(Blackhole blackhole) { + int threadCount = 200; + ExtensibleThreadPoolExecutor executor = new ExtensibleThreadPoolExecutor( + "test", new DefaultThreadPoolPluginManager(), + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + executor.prestartAllCoreThreads(); + + List tasks = getTask(threadCount, blackhole); + tasks.forEach(executor::execute); + + executor.shutdown(); + while (!executor.isTerminated()) {} + } + + @SneakyThrows + @Benchmark + public void plugin_50(Blackhole blackhole) { + int threadCount = 50; + ExtensibleThreadPoolExecutor executor = new ExtensibleThreadPoolExecutor( + "test", new DefaultThreadPoolPluginManager(), + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + executor.prestartAllCoreThreads(); + executor.register(new TaskTimeRecordPlugin()); + + List tasks = getTask(threadCount, blackhole); + tasks.forEach(executor::execute); + + executor.shutdown(); + while (!executor.isTerminated()) {} + } + + @SneakyThrows + @Benchmark + public void plugin_200(Blackhole blackhole) { + int threadCount = 200; + ExtensibleThreadPoolExecutor executor = new ExtensibleThreadPoolExecutor( + "test", new DefaultThreadPoolPluginManager(), + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + executor.prestartAllCoreThreads(); + executor.register(new TaskTimeRecordPlugin()); + + List tasks = getTask(threadCount, blackhole); + tasks.forEach(executor::execute); + + executor.shutdown(); + while (!executor.isTerminated()) {} + } + + private List getTask(int count, Blackhole blackhole) { + List tasks = new ArrayList<>(count); + for (int i = 1; i < count * 2; i++) { + int index = i; + tasks.add(() -> blackhole.consume(index)); + } + return tasks; + } + + public static void main(String[] args) throws Exception { + Options opts = new OptionsBuilder() + .include(TaskTimeRecordPluginBenchmarkTest.class.getSimpleName()) + .resultFormat(ResultFormatType.JSON) + .build(); + new Runner(opts).run(); + } + +} From 334fae1f12465a49946f34ac802d5ee850e37dfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=AC=E7=A7=B0=20Ma=20Chen?= Date: Tue, 1 Nov 2022 19:22:36 +0800 Subject: [PATCH 10/11] Update .codecov.yml --- .codecov.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.codecov.yml b/.codecov.yml index ab1c78cb..74099668 100644 --- a/.codecov.yml +++ b/.codecov.yml @@ -17,9 +17,12 @@ coverage: status: - patch: + project: default: - threshold: 0.01% + target: auto + # adjust accordingly based on how flaky your tests are + # this allows a 10% drop from the previous base commit coverage + threshold: 10% ignore: - "hippo4j-example/.*" - "docs/.*" From 05bfa3c66d28df4db1e5b2ec31ad991edc47b171 Mon Sep 17 00:00:00 2001 From: "chen.ma" Date: Tue, 1 Nov 2022 20:13:19 +0800 Subject: [PATCH 11/11] Field style refactoring and adding method logs (#878) --- .../executor/DynamicThreadPoolWrapper.java | 67 +++++++++++++++++ .../DynamicThreadPoolExecutorTest.java | 18 +++-- .../TaskTimeRecordPluginBenchmarkTest.java | 73 ++++++++++++------- 3 files changed, 125 insertions(+), 33 deletions(-) diff --git a/hippo4j-core/src/main/java/cn/hippo4j/core/executor/DynamicThreadPoolWrapper.java b/hippo4j-core/src/main/java/cn/hippo4j/core/executor/DynamicThreadPoolWrapper.java index e5dab547..8f4d2941 100644 --- a/hippo4j-core/src/main/java/cn/hippo4j/core/executor/DynamicThreadPoolWrapper.java +++ b/hippo4j-core/src/main/java/cn/hippo4j/core/executor/DynamicThreadPoolWrapper.java @@ -25,7 +25,9 @@ import lombok.NoArgsConstructor; import org.springframework.beans.factory.DisposableBean; import java.util.concurrent.Callable; +import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.ThreadPoolExecutor; /** @@ -37,10 +39,27 @@ import java.util.concurrent.ThreadPoolExecutor; @AllArgsConstructor public class DynamicThreadPoolWrapper implements DisposableBean { + /** + * Determine the unique identifier of the thread pool in the project. + * + * @param tenantId tenant id + * @param itemId project id in the team + * @param threadPoolId Thread pool identifier under the project + */ private String tenantId, itemId, threadPoolId; + /** + * Whether the thread pool has completed initialization, + * and whether to subscribe to server-side configuration change events. + * + * @param subscribeFlag subscription server configuration id + * @param initFlag initial configuration complete flag + */ private boolean subscribeFlag, initFlag; + /** + * Thread pool executor. + */ private ThreadPoolExecutor executor; public DynamicThreadPoolWrapper(String threadPoolId) { @@ -53,14 +72,62 @@ public class DynamicThreadPoolWrapper implements DisposableBean { this.subscribeFlag = true; } + /** + * Executes the given task sometime in the future. The task + * may execute in a new thread or in an existing pooled thread. + *

+ * If the task cannot be submitted for execution, either because this + * executor has been shutdown or because its capacity has been reached, + * the task is handled by the current {@code RejectedExecutionHandler}. + * + * @param command the task to execute + * @throws RejectedExecutionException at discretion of + * {@code RejectedExecutionHandler}, if the task + * cannot be accepted for execution + * @throws NullPointerException if {@code command} is null + */ public void execute(Runnable command) { executor.execute(command); } + /** + * Submits a Runnable task for execution and returns a Future + * representing that task. The Future's {@code get} method will + * return {@code null} upon successful completion. + * + * @param task the task to submit + * @return a Future representing pending completion of the task + * @throws RejectedExecutionException if the task cannot be + * scheduled for execution + * @throws NullPointerException if the task is null + */ public Future submit(Runnable task) { return executor.submit(task); } + /** + * Submits a value-returning task for execution and returns a + * Future representing the pending results of the task. The + * Future's {@code get} method will return the task's result upon + * successful completion. + * + *

+ * If you would like to immediately block waiting + * for a task, you can use constructions of the form + * {@code result = exec.submit(aCallable).get();} + * + *

Note: The {@link Executors} class includes a set of methods + * that can convert some other common closure-like objects, + * for example, {@link java.security.PrivilegedAction} to + * {@link Callable} form so they can be submitted. + * + * @param task the task to submit + * @param the type of the task's result + * @return a Future representing pending completion of the task + * @throws RejectedExecutionException if the task cannot be + * scheduled for execution + * @throws NullPointerException if the task is null + */ public Future submit(Callable task) { return executor.submit(task); } diff --git a/hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java b/hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java index cfa344a0..63d362af 100644 --- a/hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java +++ b/hippo4j-core/src/test/java/cn/hippo4j/core/executor/DynamicThreadPoolExecutorTest.java @@ -80,9 +80,9 @@ public class DynamicThreadPoolExecutorTest { @Test public void testDestroyWhenWaitForTask() { DynamicThreadPoolExecutor executor = new DynamicThreadPoolExecutor( - 1, 1, 1000L, TimeUnit.MILLISECONDS, - 1000L, true, 1000L, - new ArrayBlockingQueue<>(1), "test", Thread::new, new ThreadPoolExecutor.DiscardOldestPolicy()); + 1, 1, 1000L, TimeUnit.MILLISECONDS, + 1000L, true, 1000L, + new ArrayBlockingQueue<>(1), "test", Thread::new, new ThreadPoolExecutor.DiscardOldestPolicy()); AtomicInteger count = new AtomicInteger(0); executor.execute(() -> { @@ -96,16 +96,17 @@ public class DynamicThreadPoolExecutorTest { executor.destroy(); // waitting for terminated - while (!executor.isTerminated()){}; + while (!executor.isTerminated()) { + } ; Assert.assertEquals(2, count.get()); } @Test public void testDestroyWhenNotWaitForTask() { DynamicThreadPoolExecutor executor = new DynamicThreadPoolExecutor( - 1, 1, 1000L, TimeUnit.MILLISECONDS, - 1000L, false, 1000L, - new ArrayBlockingQueue<>(1), "test", Thread::new, new ThreadPoolExecutor.DiscardOldestPolicy()); + 1, 1, 1000L, TimeUnit.MILLISECONDS, + 1000L, false, 1000L, + new ArrayBlockingQueue<>(1), "test", Thread::new, new ThreadPoolExecutor.DiscardOldestPolicy()); AtomicInteger count = new AtomicInteger(0); executor.execute(() -> { @@ -119,7 +120,8 @@ public class DynamicThreadPoolExecutorTest { executor.destroy(); // waitting for terminated - while (!executor.isTerminated()){}; + while (!executor.isTerminated()) { + } ; Assert.assertEquals(1, count.get()); } diff --git a/hippo4j-example/hippo4j-example-core/src/test/java/cn/hippo4j/example/core/TaskTimeRecordPluginBenchmarkTest.java b/hippo4j-example/hippo4j-example-core/src/test/java/cn/hippo4j/example/core/TaskTimeRecordPluginBenchmarkTest.java index 2bf935a4..408af6e0 100644 --- a/hippo4j-example/hippo4j-example-core/src/test/java/cn/hippo4j/example/core/TaskTimeRecordPluginBenchmarkTest.java +++ b/hippo4j-example/hippo4j-example-core/src/test/java/cn/hippo4j/example/core/TaskTimeRecordPluginBenchmarkTest.java @@ -1,3 +1,20 @@ +/* + * 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.example.core; import cn.hippo4j.core.executor.ExtensibleThreadPoolExecutor; @@ -34,15 +51,16 @@ public class TaskTimeRecordPluginBenchmarkTest { public void origin_200(Blackhole blackhole) { int threadCount = 200; ThreadPoolExecutor executor = new ThreadPoolExecutor( - threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, - new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); executor.prestartAllCoreThreads(); List tasks = getTask(threadCount, blackhole); tasks.forEach(executor::execute); executor.shutdown(); - while (!executor.isTerminated()) {} + while (!executor.isTerminated()) { + } } @SneakyThrows @@ -50,15 +68,16 @@ public class TaskTimeRecordPluginBenchmarkTest { public void origin_50(Blackhole blackhole) { int threadCount = 50; ThreadPoolExecutor executor = new ThreadPoolExecutor( - threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, - new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); executor.prestartAllCoreThreads(); List tasks = getTask(threadCount, blackhole); tasks.forEach(executor::execute); executor.shutdown(); - while (!executor.isTerminated()) {} + while (!executor.isTerminated()) { + } } @SneakyThrows @@ -66,16 +85,17 @@ public class TaskTimeRecordPluginBenchmarkTest { public void not_plugin_50(Blackhole blackhole) { int threadCount = 50; ExtensibleThreadPoolExecutor executor = new ExtensibleThreadPoolExecutor( - "test", new DefaultThreadPoolPluginManager(), - threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, - new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + "test", new DefaultThreadPoolPluginManager(), + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); executor.prestartAllCoreThreads(); List tasks = getTask(threadCount, blackhole); tasks.forEach(executor::execute); executor.shutdown(); - while (!executor.isTerminated()) {} + while (!executor.isTerminated()) { + } } @SneakyThrows @@ -83,16 +103,17 @@ public class TaskTimeRecordPluginBenchmarkTest { public void not_plugin_200(Blackhole blackhole) { int threadCount = 200; ExtensibleThreadPoolExecutor executor = new ExtensibleThreadPoolExecutor( - "test", new DefaultThreadPoolPluginManager(), - threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, - new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + "test", new DefaultThreadPoolPluginManager(), + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); executor.prestartAllCoreThreads(); List tasks = getTask(threadCount, blackhole); tasks.forEach(executor::execute); executor.shutdown(); - while (!executor.isTerminated()) {} + while (!executor.isTerminated()) { + } } @SneakyThrows @@ -100,9 +121,9 @@ public class TaskTimeRecordPluginBenchmarkTest { public void plugin_50(Blackhole blackhole) { int threadCount = 50; ExtensibleThreadPoolExecutor executor = new ExtensibleThreadPoolExecutor( - "test", new DefaultThreadPoolPluginManager(), - threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, - new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + "test", new DefaultThreadPoolPluginManager(), + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); executor.prestartAllCoreThreads(); executor.register(new TaskTimeRecordPlugin()); @@ -110,7 +131,8 @@ public class TaskTimeRecordPluginBenchmarkTest { tasks.forEach(executor::execute); executor.shutdown(); - while (!executor.isTerminated()) {} + while (!executor.isTerminated()) { + } } @SneakyThrows @@ -118,9 +140,9 @@ public class TaskTimeRecordPluginBenchmarkTest { public void plugin_200(Blackhole blackhole) { int threadCount = 200; ExtensibleThreadPoolExecutor executor = new ExtensibleThreadPoolExecutor( - "test", new DefaultThreadPoolPluginManager(), - threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, - new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); + "test", new DefaultThreadPoolPluginManager(), + threadCount, threadCount, 1000L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadCount), Thread::new, new ThreadPoolExecutor.DiscardPolicy()); executor.prestartAllCoreThreads(); executor.register(new TaskTimeRecordPlugin()); @@ -128,7 +150,8 @@ public class TaskTimeRecordPluginBenchmarkTest { tasks.forEach(executor::execute); executor.shutdown(); - while (!executor.isTerminated()) {} + while (!executor.isTerminated()) { + } } private List getTask(int count, Blackhole blackhole) { @@ -142,9 +165,9 @@ public class TaskTimeRecordPluginBenchmarkTest { public static void main(String[] args) throws Exception { Options opts = new OptionsBuilder() - .include(TaskTimeRecordPluginBenchmarkTest.class.getSimpleName()) - .resultFormat(ResultFormatType.JSON) - .build(); + .include(TaskTimeRecordPluginBenchmarkTest.class.getSimpleName()) + .resultFormat(ResultFormatType.JSON) + .build(); new Runner(opts).run(); }