<dependency>
<groupId>com.alibaba.cloudgroupId>
<artifactId>spring-cloud-starter-alibaba-nacos-configartifactId>
<version>2.2.9.RELEASEversion>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
spring:
application:
name: big-market-app
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: 71f7c141-xxxx-xxxx-xxxx-6b1530a0xxxx
group: MARKET_GROUP
file-extension: yaml
refresh-enabled: true
profiles:
active: dev
// d:\develop\workspace\big-market\big-market-app\src\main\java\com\market\config\DynamicThreadPoolConfig.java
package com.market.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "thread-pool.market")
public class DynamicThreadPoolConfig {
private int coreSize = 10;
private int maxSize = 20;
private int queueCapacity = 1000;
private int keepAliveSeconds = 60;
private String threadNamePrefix = "market-";
}
// d:\develop\workspace\big-market\big-market-app\src\main\java\com\market\config\ResizableCapacityQueue.java
package com.market.config;
import java.util.ArrayDeque;
import java.util.Collection;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ResizableCapacityQueue<E> implements BlockingQueue<E> {
private final ReentrantLock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition();
private final Condition notFull = lock.newCondition();
private final ArrayDeque<E> deque = new ArrayDeque<>();
private volatile int capacity;
public ResizableCapacityQueue(int initialCapacity) {
this.capacity = initialCapacity;
}
// 核心方法:动态调整容量
public void setCapacity(int newCapacity) {
if (newCapacity <= 0) {
throw new IllegalArgumentException("容量必须为正数");
}
lock.lock();
try {
int oldCapacity = this.capacity;
this.capacity = newCapacity;
// 如果新容量大于旧容量,唤醒等待的生产者
if (newCapacity > oldCapacity) {
notFull.signalAll();
}
} finally {
lock.unlock();
}
}
@Override
public boolean offer(E e) {
lock.lock();
try {
if (deque.size() == capacity) {
return false;
}
deque.add(e);
notEmpty.signal();
return true;
} finally {
lock.unlock();
}
}
@Override
public void put(E e) throws InterruptedException {
lock.lockInterruptibly();
try {
while (deque.size() == capacity) {
notFull.await();
}
deque.add(e);
notEmpty.signal();
} finally {
lock.unlock();
}
}
@Override
public E take() throws InterruptedException {
lock.lockInterruptibly();
try {
while (deque.isEmpty()) {
notEmpty.await();
}
E e = deque.poll();
notFull.signal();
return e;
} finally {
lock.unlock();
}
}
@Override
public int size() {
lock.lock();
try {
return deque.size();
} finally {
lock.unlock();
}
}
// 实现其他BlockingQueue接口方法...
@Override
public boolean add(E e) { return offer(e); }
@Override
public boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException { return offer(e); }
@Override
public E poll() { return deque.poll(); }
@Override
public E poll(long timeout, TimeUnit unit) throws InterruptedException { return deque.poll(); }
@Override
public E peek() { return deque.peek(); }
@Override
public int remainingCapacity() { return capacity - size(); }
@Override
public boolean remove(Object o) { return deque.remove(o); }
@Override
public boolean contains(Object o) { return deque.contains(o); }
@Override
public int drainTo(Collection<? super E> c) { return 0; }
@Override
public int drainTo(Collection<? super E> c, int maxElements) { return 0; }
@Override
public boolean isEmpty() { return deque.isEmpty(); }
@Override
public Object[] toArray() { return deque.toArray(); }
@Override
public <T> T[] toArray(T[] a) { return deque.toArray(a); }
@Override
public boolean containsAll(Collection<?> c) { return deque.containsAll(c); }
@Override
public boolean addAll(Collection<? extends E> c) { return deque.addAll(c); }
@Override
public boolean removeAll(Collection<?> c) { return deque.removeAll(c); }
@Override
public boolean retainAll(Collection<?> c) { return deque.retainAll(c); }
@Override
public void clear() { deque.clear(); }
}
// d:\develop\workspace\big-market\big-market-app\src\main\java\com\market\config\ThreadPoolFactory.java
package com.market.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@Slf4j
@Configuration
public class ThreadPoolFactory {
@Autowired
private DynamicThreadPoolConfig threadPoolConfig;
@Bean("marketTaskExecutor")
public ThreadPoolTaskExecutor marketTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor() {
@Override
protected BlockingQueue<Runnable> createQueue(int queueCapacity) {
// 使用自定义可调整容量队列替代默认队列
return new ResizableCapacityQueue<>(queueCapacity);
}
};
executor.setCorePoolSize(threadPoolConfig.getCoreSize());
executor.setMaxPoolSize(threadPoolConfig.getMaxSize());
executor.setQueueCapacity(threadPoolConfig.getQueueCapacity());
executor.setKeepAliveSeconds(threadPoolConfig.getKeepAliveSeconds());
executor.setThreadNamePrefix(threadPoolConfig.getThreadNamePrefix());
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
log.info("初始化线程池完成: {}", threadPoolConfig);
return executor;
}
}
// d:\develop\workspace\big-market\big-market-app\src\main\java\com\market\listener\NacosThreadPoolListener.java
package com.market.listener;
import com.alibaba.cloud.nacos.NacosConfigReceivedEvent;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.market.config.DynamicThreadPoolConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.util.Map;
@Slf4j
@Component
public class NacosThreadPoolListener {
@Autowired
private DynamicThreadPoolConfig threadPoolConfig;
@Autowired
private ThreadPoolTaskExecutor marketTaskExecutor;
@Autowired
private ObjectMapper objectMapper;
@EventListener(NacosConfigReceivedEvent.class)
public void onConfigReceived(NacosConfigReceivedEvent event) {
try {
// 只处理线程池配置变更
if ("big-market-app-threadpool.yaml".equals(event.getDataId())) {
String configContent = event.getContent();
if (StringUtils.hasText(configContent)) {
// 解析配置内容
Map<String, Object> configMap = objectMapper.readValue(configContent, Map.class);
Map<String, Integer> threadPoolMap = (Map<String, Integer>) configMap.get("thread-pool");
if (threadPoolMap != null && threadPoolMap.containsKey("market")) {
Map<String, Integer> marketConfig = (Map<String, Integer>) threadPoolMap.get("market");
updateThreadPoolConfig(marketConfig);
}
}
}
} catch (Exception e) {
log.error("处理线程池配置变更异常", e);
}
}
private void updateThreadPoolConfig(Map<String, Integer> newConfig) {
if (newConfig == null) return;
// 更新配置类
if (newConfig.containsKey("coreSize")) {
int coreSize = newConfig.get("coreSize");
threadPoolConfig.setCoreSize(coreSize);
marketTaskExecutor.setCorePoolSize(coreSize);
log.info("更新核心线程数: {}", coreSize);
}
if (newConfig.containsKey("maxSize")) {
int maxSize = newConfig.get("maxSize");
threadPoolConfig.setMaxSize(maxSize);
marketTaskExecutor.setMaxPoolSize(maxSize);
log.info("更新最大线程数: {}", maxSize);
}
if (newConfig.containsKey("queueCapacity")) {
int queueCapacity = newConfig.get("queueCapacity");
threadPoolConfig.setQueueCapacity(queueCapacity);
// 获取实际工作队列并调整容量
BlockingQueue<Runnable> queue = marketTaskExecutor.getThreadPoolExecutor().getQueue();
if (queue instanceof ResizableCapacityQueue) {
((ResizableCapacityQueue<Runnable>) queue).setCapacity(queueCapacity);
log.info("更新队列容量: {}", queueCapacity);
} else {
log.error("工作队列不是ResizableCapacityQueue类型,无法更新容量");
}
}
}
}
thread-pool:
market:
coreSize: 15
maxSize: 30
queueCapacity: 2000
keepAliveSeconds: 60
threadNamePrefix: market-
// d:\develop\workspace\big-market\big-market-app\src\main\java\com\market\service\TaskService.java
package com.market.service;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class TaskService {
@Autowired
private ThreadPoolTaskExecutor marketTaskExecutor;
public void submitTask(Runnable task) {
marketTaskExecutor.submit(() -> {
try {
task.run();
} catch (Exception e) {
log.error("任务执行异常", e);
}
});
}
// 获取当前线程池状态
public String getThreadPoolStatus() {
return String.format(
"线程池状态: 核心线程数=%d, 最大线程数=%d, 活跃线程数=%d, 队列大小=%d, 已完成任务数=%d",
marketTaskExecutor.getCorePoolSize(),
marketTaskExecutor.getMaxPoolSize(),
marketTaskExecutor.getActiveCount(),
marketTaskExecutor.getThreadPoolExecutor().getQueue().size(),
marketTaskExecutor.getThreadPoolExecutor().getCompletedTaskCount()
);
}
}
通过以上实现,可在Nacos控制台动态调整线程池参数,包括核心线程数、最大线程数和队列容量,应对不同时段的流量变化,特别适合大营销项目中的秒杀、拼团等高并发场景。
通过以上实现,可在Nacos控制台动态调整线程池参数,应对不同时段的流量变化,特别适合大营销项目中的秒杀、拼团等高并发场景。