|
@@ -0,0 +1,161 @@
|
|
|
|
|
+package com.fs.company.config;
|
|
|
|
|
+
|
|
|
|
|
+import org.springframework.context.annotation.Bean;
|
|
|
|
|
+import org.springframework.context.annotation.Configuration;
|
|
|
|
|
+import org.springframework.scheduling.annotation.EnableAsync;
|
|
|
|
|
+
|
|
|
|
|
+import java.util.concurrent.*;
|
|
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * @author MixLiu
|
|
|
|
|
+ * @date 2026/3/26 10:04
|
|
|
|
|
+ * @description qwHandle线程池配置,提供给@Async注解使用
|
|
|
|
|
+ */
|
|
|
|
|
+@Configuration
|
|
|
|
|
+@EnableAsync
|
|
|
|
|
+public class QwHandleExectorConfig {
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 核心线程数
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final int CORE_POOL_SIZE = 8;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 最大线程数
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final int MAX_POOL_SIZE = 16;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 队列容量
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final int QUEUE_CAPACITY = 5000;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 线程空闲时间(分钟)
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final int KEEP_ALIVE_MINUTES = 30;
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 线程名称前缀
|
|
|
|
|
+ */
|
|
|
|
|
+ private static final String THREAD_NAME_PREFIX = "qwHandle-";
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 自定义任务队列,优先创建新线程而不是进入队列
|
|
|
|
|
+ * ThreadPoolExecutor的任务提交逻辑:
|
|
|
|
|
+ * 1. 线程数 < corePoolSize -> 创建新线程
|
|
|
|
|
+ * 2. 线程数 >= corePoolSize -> 尝试入队(调用offer方法)
|
|
|
|
|
+ * 3. offer返回false且线程数 < maxPoolSize -> 创建新线程
|
|
|
|
|
+ * 4. offer返回false且线程数 >= maxPoolSize -> 执行拒绝策略
|
|
|
|
|
+ *
|
|
|
|
|
+ * 通过重写offer方法,让其在未达最大线程数时返回false,从而优先创建新线程
|
|
|
|
|
+ */
|
|
|
|
|
+ private static class PriorityThreadQueue extends LinkedBlockingQueue<Runnable> {
|
|
|
|
|
+
|
|
|
|
|
+ private static final long serialVersionUID = 1L;
|
|
|
|
|
+
|
|
|
|
|
+ private transient volatile ThreadPoolExecutor executor;
|
|
|
|
|
+
|
|
|
|
|
+ public PriorityThreadQueue(int capacity) {
|
|
|
|
|
+ super(capacity);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ public void setExecutor(ThreadPoolExecutor executor) {
|
|
|
|
|
+ this.executor = executor;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public boolean offer(Runnable o) {
|
|
|
|
|
+ ThreadPoolExecutor exec = this.executor;
|
|
|
|
|
+ if (exec != null) {
|
|
|
|
|
+ int poolSize = exec.getPoolSize();
|
|
|
|
|
+ int maxPoolSize = exec.getMaximumPoolSize();
|
|
|
|
|
+ // 如果线程数未达到最大值,返回false让线程池创建新线程
|
|
|
|
|
+ if (poolSize < maxPoolSize) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 线程数已达最大值,任务入队
|
|
|
|
|
+ return super.offer(o);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 强制入队方法,供拒绝策略使用
|
|
|
|
|
+ */
|
|
|
|
|
+ public boolean forceOffer(Runnable o) {
|
|
|
|
|
+ return super.offer(o);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 自定义拒绝策略:调用者执行
|
|
|
|
|
+ */
|
|
|
|
|
+ private static class CallerRunsPolicy implements RejectedExecutionHandler {
|
|
|
|
|
+
|
|
|
|
|
+ private final PriorityThreadQueue queue;
|
|
|
|
|
+
|
|
|
|
|
+ public CallerRunsPolicy(PriorityThreadQueue queue) {
|
|
|
|
|
+ this.queue = queue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
|
|
|
|
|
+ if (executor.isShutdown()) {
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ // 尝试强制入队
|
|
|
|
|
+ if (!queue.forceOffer(r)) {
|
|
|
|
|
+ // 入队失败,由调用者线程执行
|
|
|
|
|
+ r.run();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 自定义线程工厂
|
|
|
|
|
+ */
|
|
|
|
|
+ private static class QwHandleThreadFactory implements ThreadFactory {
|
|
|
|
|
+
|
|
|
|
|
+ private final AtomicInteger threadNumber = new AtomicInteger(1);
|
|
|
|
|
+ private final String namePrefix;
|
|
|
|
|
+
|
|
|
|
|
+ QwHandleThreadFactory() {
|
|
|
|
|
+ namePrefix = THREAD_NAME_PREFIX;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public Thread newThread(Runnable r) {
|
|
|
|
|
+ Thread t = new Thread(r, namePrefix + threadNumber.getAndIncrement());
|
|
|
|
|
+ t.setDaemon(false);
|
|
|
|
|
+ t.setPriority(Thread.NORM_PRIORITY);
|
|
|
|
|
+ return t;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 配置qwHandle线程池
|
|
|
|
|
+ */
|
|
|
|
|
+ @Bean(name = "qwHandleExec")
|
|
|
|
|
+ public ThreadPoolExecutor qwHandleExecutor() {
|
|
|
|
|
+ PriorityThreadQueue queue = new PriorityThreadQueue(QUEUE_CAPACITY);
|
|
|
|
|
+
|
|
|
|
|
+ ThreadPoolExecutor executor = new ThreadPoolExecutor(
|
|
|
|
|
+ CORE_POOL_SIZE,
|
|
|
|
|
+ MAX_POOL_SIZE,
|
|
|
|
|
+ KEEP_ALIVE_MINUTES,
|
|
|
|
|
+ TimeUnit.MINUTES,
|
|
|
|
|
+ queue,
|
|
|
|
|
+ new QwHandleThreadFactory(),
|
|
|
|
|
+ new CallerRunsPolicy(queue)
|
|
|
|
|
+ );
|
|
|
|
|
+
|
|
|
|
|
+ // 允许核心线程超时
|
|
|
|
|
+ executor.allowCoreThreadTimeOut(true);
|
|
|
|
|
+
|
|
|
|
|
+ // 将队列与执行器关联
|
|
|
|
|
+ queue.setExecutor(executor);
|
|
|
|
|
+
|
|
|
|
|
+ return executor;
|
|
|
|
|
+ }
|
|
|
|
|
+}
|