From 4b355067eba02c788b0cc97540f8bc256d0ea1a0 Mon Sep 17 00:00:00 2001 From: dqjdda <201507802@qq.com> Date: Thu, 31 Oct 2019 18:20:56 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BD=BF=E7=94=A8=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E6=B1=A0=E6=89=A7=E8=A1=8C=E5=AE=9A=E6=97=B6?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=EF=BC=8C=E9=81=BF=E5=85=8D=E7=A8=8B=E5=BA=8F?= =?UTF-8?q?OOM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/thread/AsyncTaskExecutePool.java | 58 +++++++++++++++++++ .../config/thread/AsyncTaskProperties.java | 24 ++++++++ .../config/thread/TheadFactoryName.java | 48 +++++++++++++++ .../config/thread/ThreadPoolExecutorUtil.java | 27 +++++++++ .../modules/quartz/task/TestTask.java | 2 +- .../modules/quartz/utils/ExecutionJob.java | 12 ++-- .../src/main/resources/config/application.yml | 11 ++++ 7 files changed, 175 insertions(+), 7 deletions(-) create mode 100644 eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskExecutePool.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskProperties.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/config/thread/TheadFactoryName.java create mode 100644 eladmin-system/src/main/java/me/zhengjie/config/thread/ThreadPoolExecutorUtil.java diff --git a/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskExecutePool.java b/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskExecutePool.java new file mode 100644 index 00000000..cc3b21c5 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskExecutePool.java @@ -0,0 +1,58 @@ +package me.zhengjie.config.thread; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import java.lang.reflect.Method; +import java.util.concurrent.Executor; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 异步任务线程池装配类 + * @author https://juejin.im/entry/5abb8f6951882555677e9da2 + * @date 2019年10月31日15:06:18 + */ +@Slf4j +@Configuration +public class AsyncTaskExecutePool implements AsyncConfigurer { + + //注入配置类 + private final AsyncTaskProperties config; + + public AsyncTaskExecutePool(AsyncTaskProperties config) { + this.config = config; + } + + @Override + public Executor getAsyncExecutor() { + ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); + //核心线程池大小 + executor.setCorePoolSize(config.getCorePoolSize()); + //最大线程数 + executor.setMaxPoolSize(config.getMaxPoolSize()); + //队列容量 + executor.setQueueCapacity(config.getQueueCapacity()); + //活跃时间 + executor.setKeepAliveSeconds(config.getKeepAliveSeconds()); + //线程名字前缀 + executor.setThreadNamePrefix("el-executor-"); + // setRejectedExecutionHandler:当pool已经达到max size的时候,如何处理新任务 + // CallerRunsPolicy:不在新线程中执行任务,而是由调用者所在的线程来执行 + executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + executor.initialize(); + return executor; + } + + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return new AsyncUncaughtExceptionHandler() { + @Override + public void handleUncaughtException(Throwable throwable, Method method, Object... objects) { + log.error("=========================="+throwable.getMessage()+"=======================", throwable); + log.error("exception method:"+method.getName()); + } + }; + } +} diff --git a/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskProperties.java b/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskProperties.java new file mode 100644 index 00000000..f836fa09 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/config/thread/AsyncTaskProperties.java @@ -0,0 +1,24 @@ +package me.zhengjie.config.thread; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 线程池配置属性类 + * @author https://juejin.im/entry/5abb8f6951882555677e9da2 + * @date 2019年10月31日14:58:18 + */ +@Data +@Component +@ConfigurationProperties(prefix = "task.pool") +public class AsyncTaskProperties { + + private int corePoolSize; + + private int maxPoolSize; + + private int keepAliveSeconds; + + private int queueCapacity; +} diff --git a/eladmin-system/src/main/java/me/zhengjie/config/thread/TheadFactoryName.java b/eladmin-system/src/main/java/me/zhengjie/config/thread/TheadFactoryName.java new file mode 100644 index 00000000..d5cb656c --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/config/thread/TheadFactoryName.java @@ -0,0 +1,48 @@ +package me.zhengjie.config.thread; + +import org.springframework.stereotype.Component; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * 自定义线程名称 + * @author Zheng Jie + * @date 2019年10月31日17:49:55 + */ +@Component +public class TheadFactoryName implements ThreadFactory { + + private static final AtomicInteger poolNumber = new AtomicInteger(1); + private final ThreadGroup group; + private final AtomicInteger threadNumber = new AtomicInteger(1); + private final String namePrefix; + + public TheadFactoryName() { + this("el-pool"); + } + + private TheadFactoryName(String name){ + SecurityManager s = System.getSecurityManager(); + group = (s != null) ? s.getThreadGroup() : + Thread.currentThread().getThreadGroup(); + //此时namePrefix就是 name + 第几个用这个工厂创建线程池的 + this.namePrefix = name + + poolNumber.getAndIncrement(); + } + + @Override + public Thread newThread(Runnable r) { + //此时线程的名字 就是 namePrefix + -thread- + 这个线程池中第几个执行的线程 + Thread t = new Thread(group, r, + namePrefix + "-thread-"+threadNumber.getAndIncrement(), + 0); + if (t.isDaemon()) { + t.setDaemon(false); + } + if (t.getPriority() != Thread.NORM_PRIORITY) { + t.setPriority(Thread.NORM_PRIORITY); + } + return t; + } +} diff --git a/eladmin-system/src/main/java/me/zhengjie/config/thread/ThreadPoolExecutorUtil.java b/eladmin-system/src/main/java/me/zhengjie/config/thread/ThreadPoolExecutorUtil.java new file mode 100644 index 00000000..963995fb --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/config/thread/ThreadPoolExecutorUtil.java @@ -0,0 +1,27 @@ +package me.zhengjie.config.thread; + +import me.zhengjie.utils.SpringContextHolder; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * 用于获取自定义线程池 + * @author Zheng Jie + * @date 2019年10月31日18:16:47 + */ +public class ThreadPoolExecutorUtil { + + public static ThreadPoolExecutor getPoll(){ + AsyncTaskProperties properties = SpringContextHolder.getBean(AsyncTaskProperties.class); + return new ThreadPoolExecutor( + properties.getCorePoolSize(), + properties.getMaxPoolSize(), + properties.getKeepAliveSeconds(), + TimeUnit.SECONDS, + new ArrayBlockingQueue(properties.getQueueCapacity()), + new TheadFactoryName() + ); + } +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java index 025edd90..757703bb 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/task/TestTask.java @@ -11,7 +11,7 @@ import org.springframework.stereotype.Component; @Slf4j @Component public class TestTask { - + public void run(){ log.info("执行成功"); } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java index eb442381..1c0713fd 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/quartz/utils/ExecutionJob.java @@ -1,5 +1,7 @@ package me.zhengjie.modules.quartz.utils; +import me.zhengjie.config.thread.TheadFactoryName; +import me.zhengjie.config.thread.ThreadPoolExecutorUtil; import me.zhengjie.modules.quartz.domain.QuartzJob; import me.zhengjie.modules.quartz.domain.QuartzLog; import me.zhengjie.modules.quartz.repository.QuartzLogRepository; @@ -11,9 +13,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.quartz.QuartzJobBean; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; +import java.util.concurrent.*; /** * 参考人人开源,https://gitee.com/renrenio/renren-security @@ -25,8 +25,8 @@ public class ExecutionJob extends QuartzJobBean { private Logger logger = LoggerFactory.getLogger(this.getClass()); - // 建议自定义线程池实现方式,该处仅供参考 - private ExecutorService executorService = Executors.newSingleThreadExecutor(); + // 该处仅供参考 + private final static ThreadPoolExecutor executor = ThreadPoolExecutorUtil.getPoll(); @Override @SuppressWarnings("unchecked") @@ -48,7 +48,7 @@ public class ExecutionJob extends QuartzJobBean { logger.info("任务准备执行,任务名称:{}", quartzJob.getJobName()); QuartzRunnable task = new QuartzRunnable(quartzJob.getBeanName(), quartzJob.getMethodName(), quartzJob.getParams()); - Future future = executorService.submit(task); + Future future = executor.submit(task); future.get(); long times = System.currentTimeMillis() - startTime; log.setTime(times); diff --git a/eladmin-system/src/main/resources/config/application.yml b/eladmin-system/src/main/resources/config/application.yml index c45c9529..6ebf8549 100644 --- a/eladmin-system/src/main/resources/config/application.yml +++ b/eladmin-system/src/main/resources/config/application.yml @@ -29,6 +29,17 @@ spring: #连接超时时间 timeout: 5000 +task: + pool: + # 核心线程池大小 + core-pool-size: 10 + # 最大线程数 + max-pool-size: 30 + # 活跃时间 + keep-alive-seconds: 60 + # 队列容量 + queue-capacity: 50 + #七牛云 qiniu: # 文件大小 /M