mirror of https://github.com/longtai-cn/hippo4j
parent
e12b34c2e2
commit
da0c9318c9
@ -0,0 +1,33 @@
|
|||||||
|
HELP.md
|
||||||
|
target/
|
||||||
|
!.mvn/wrapper/maven-wrapper.jar
|
||||||
|
!**/src/main/**/target/
|
||||||
|
!**/src/test/**/target/
|
||||||
|
|
||||||
|
### STS ###
|
||||||
|
.apt_generated
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
|
.settings
|
||||||
|
.springBeans
|
||||||
|
.sts4-cache
|
||||||
|
|
||||||
|
### IntelliJ IDEA ###
|
||||||
|
.idea
|
||||||
|
*.iws
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
|
||||||
|
### NetBeans ###
|
||||||
|
/nbproject/private/
|
||||||
|
/nbbuild/
|
||||||
|
/dist/
|
||||||
|
/nbdist/
|
||||||
|
/.nb-gradle/
|
||||||
|
build/
|
||||||
|
!**/src/main/**/build/
|
||||||
|
!**/src/test/**/build/
|
||||||
|
|
||||||
|
### VS Code ###
|
||||||
|
.vscode/
|
@ -0,0 +1,22 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>io.dynamic-threadpool</groupId>
|
||||||
|
<artifactId>parent</artifactId>
|
||||||
|
<version>${revision}</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<artifactId>common</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>common</name>
|
||||||
|
<description>Demo project for Spring Boot</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,56 @@
|
|||||||
|
package io.dynamict.hreadpool.common.toolkit;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MD5 Util.
|
||||||
|
*
|
||||||
|
* @author chen.ma
|
||||||
|
* @date 2021/6/22 17:55
|
||||||
|
*/
|
||||||
|
public class Md5Util {
|
||||||
|
|
||||||
|
private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||||
|
|
||||||
|
private static final ThreadLocal<MessageDigest> MESSAGE_DIGEST_LOCAL = ThreadLocal.withInitial(() -> {
|
||||||
|
try {
|
||||||
|
return MessageDigest.getInstance("MD5");
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
public static String md5Hex(byte[] bytes) throws NoSuchAlgorithmException {
|
||||||
|
try {
|
||||||
|
MessageDigest messageDigest = MESSAGE_DIGEST_LOCAL.get();
|
||||||
|
if (messageDigest != null) {
|
||||||
|
return encodeHexString(messageDigest.digest(bytes));
|
||||||
|
}
|
||||||
|
throw new NoSuchAlgorithmException("MessageDigest get MD5 instance error");
|
||||||
|
} finally {
|
||||||
|
MESSAGE_DIGEST_LOCAL.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String md5Hex(String value, String encode) {
|
||||||
|
try {
|
||||||
|
return md5Hex(value.getBytes(encode));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encodeHexString(byte[] bytes) {
|
||||||
|
int l = bytes.length;
|
||||||
|
|
||||||
|
char[] out = new char[l << 1];
|
||||||
|
|
||||||
|
for (int i = 0, j = 0; i < l; i++) {
|
||||||
|
out[j++] = DIGITS_LOWER[(0xF0 & bytes[i]) >>> 4];
|
||||||
|
out[j++] = DIGITS_LOWER[0x0F & bytes[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return new String(out);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package io.dynamic.threadpool.starter.adapter;
|
||||||
|
|
||||||
|
import io.dynamic.threadpool.starter.core.ThreadPoolDynamicRefresh;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ConfigAdapter.
|
||||||
|
*
|
||||||
|
* @author chen.ma
|
||||||
|
* @date 2021/6/22 21:29
|
||||||
|
*/
|
||||||
|
public class ConfigAdapter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调修改线程池配置
|
||||||
|
*
|
||||||
|
* @param tpId
|
||||||
|
* @param config
|
||||||
|
*/
|
||||||
|
public void callbackConfig(String tpId, String config) {
|
||||||
|
ThreadPoolDynamicRefresh.refreshDynamicPool(tpId, config);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package io.dynamic.threadpool.starter.adapter;
|
||||||
|
|
||||||
|
import cn.hutool.core.thread.ThreadFactoryBuilder;
|
||||||
|
import io.dynamic.threadpool.starter.operation.ThreadPoolOperation;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态线程池配置适配器
|
||||||
|
*
|
||||||
|
* @author chen.ma
|
||||||
|
* @date 2021/6/22 20:17
|
||||||
|
*/
|
||||||
|
public class ThreadPoolConfigAdapter extends ConfigAdapter {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ThreadPoolOperation threadPoolOperation;
|
||||||
|
|
||||||
|
private ExecutorService executorService = new ThreadPoolExecutor(
|
||||||
|
2,
|
||||||
|
4,
|
||||||
|
0,
|
||||||
|
TimeUnit.MILLISECONDS,
|
||||||
|
new ArrayBlockingQueue(1),
|
||||||
|
new ThreadFactoryBuilder().setNamePrefix("threadPool-config").build(),
|
||||||
|
new ThreadPoolExecutor.DiscardOldestPolicy());
|
||||||
|
|
||||||
|
public void subscribeConfig(List<String> tpIds) {
|
||||||
|
tpIds.forEach(each -> threadPoolOperation.subscribeConfig(each, executorService, (tpId, config) -> callbackConfig(tpId, config)));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package io.dynamic.threadpool.starter.config;
|
||||||
|
|
||||||
|
import io.dynamic.threadpool.starter.adapter.ThreadPoolConfigAdapter;
|
||||||
|
import io.dynamic.threadpool.starter.core.ConfigService;
|
||||||
|
import io.dynamic.threadpool.starter.core.ThreadPoolConfigService;
|
||||||
|
import io.dynamic.threadpool.starter.core.ThreadPoolRunListener;
|
||||||
|
import io.dynamic.threadpool.starter.operation.ThreadPoolOperation;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态线程池自动装配类
|
||||||
|
*
|
||||||
|
* @author chen.ma
|
||||||
|
* @date 2021/6/22 09:20
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
@AllArgsConstructor
|
||||||
|
@EnableConfigurationProperties(DynamicThreadPoolProperties.class)
|
||||||
|
@ConditionalOnProperty(prefix = DynamicThreadPoolProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
|
||||||
|
public class DynamicThreadPoolAutoConfiguration {
|
||||||
|
|
||||||
|
private final DynamicThreadPoolProperties properties;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ConfigService configService() {
|
||||||
|
return new ThreadPoolConfigService();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ThreadPoolRunListener threadPoolRunListener() {
|
||||||
|
return new ThreadPoolRunListener();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ThreadPoolConfigAdapter threadPoolConfigAdapter() {
|
||||||
|
return new ThreadPoolConfigAdapter();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public ThreadPoolOperation threadPoolOperation() {
|
||||||
|
return new ThreadPoolOperation();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,32 @@
|
|||||||
|
package io.dynamic.threadpool.starter.config;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 动态线程池配置
|
||||||
|
*
|
||||||
|
* @author chen.ma
|
||||||
|
* @date 2021/6/22 09:14
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ConfigurationProperties(prefix = DynamicThreadPoolProperties.PREFIX)
|
||||||
|
public class DynamicThreadPoolProperties {
|
||||||
|
|
||||||
|
public static final String PREFIX = "spring.threadpool.dynamic";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命名空间
|
||||||
|
*/
|
||||||
|
private String namespace;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 项目 Id
|
||||||
|
*/
|
||||||
|
private String itemId;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package io.dynamic.threadpool.starter.core;
|
||||||
|
|
||||||
|
import io.dynamic.threadpool.starter.listener.Listener;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置服务
|
||||||
|
*
|
||||||
|
* @author chen.ma
|
||||||
|
* @date 2021/6/21 21:49
|
||||||
|
*/
|
||||||
|
public interface ConfigService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加监听器, 如果服务端发生变更, 客户端会使用监听器进行回调
|
||||||
|
*
|
||||||
|
* @param tpId
|
||||||
|
* @param listener
|
||||||
|
*/
|
||||||
|
void addListener(String tpId, Listener listener);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
package io.dynamic.threadpool.starter.core;
|
||||||
|
|
||||||
|
import io.dynamic.threadpool.starter.listener.ClientWorker;
|
||||||
|
import io.dynamic.threadpool.starter.listener.Listener;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线程池配置服务
|
||||||
|
*
|
||||||
|
* @author chen.ma
|
||||||
|
* @date 2021/6/21 21:50
|
||||||
|
*/
|
||||||
|
public class ThreadPoolConfigService implements ConfigService {
|
||||||
|
|
||||||
|
private final ClientWorker clientWorker;
|
||||||
|
|
||||||
|
public ThreadPoolConfigService() {
|
||||||
|
clientWorker = new ClientWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addListener(String tpId, Listener listener) {
|
||||||
|
clientWorker.addTenantListeners(tpId, Arrays.asList(listener));
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,162 @@
|
|||||||
package io.dynamic.threadpool.starter.listener;
|
package io.dynamic.threadpool.starter.listener;
|
||||||
|
|
||||||
|
import io.dynamic.threadpool.starter.core.CacheData;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 客户端监听
|
* 客户端监听
|
||||||
*
|
*
|
||||||
* @author chen.ma
|
* @author chen.ma
|
||||||
* @date 2021/6/20 18:34
|
* @date 2021/6/20 18:34
|
||||||
*/
|
*/
|
||||||
|
@Slf4j
|
||||||
public class ClientWorker {
|
public class ClientWorker {
|
||||||
|
|
||||||
|
private double currentLongingTaskCount = 0;
|
||||||
|
|
||||||
|
private final ScheduledExecutorService executor;
|
||||||
|
|
||||||
|
private final ScheduledExecutorService executorService;
|
||||||
|
|
||||||
|
private final ConcurrentHashMap<String, CacheData> cacheMap = new ConcurrentHashMap(16);
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public ClientWorker() {
|
||||||
|
this.executor = Executors.newScheduledThreadPool(1, r -> {
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setName("io.dynamic.threadPool.client.Worker.executor");
|
||||||
|
t.setDaemon(true);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
|
||||||
|
int threadSize = Runtime.getRuntime().availableProcessors();
|
||||||
|
this.executorService = Executors.newScheduledThreadPool(threadSize, r -> {
|
||||||
|
Thread t = new Thread(r);
|
||||||
|
t.setName("io.dynamic.threadPool.client.Worker.longPolling.executor");
|
||||||
|
t.setDaemon(true);
|
||||||
|
return t;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.executor.scheduleWithFixedDelay(() -> {
|
||||||
|
try {
|
||||||
|
checkConfigInfo();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
log.error("[sub-check] rotate check error", e);
|
||||||
|
}
|
||||||
|
}, 1L, 10L, TimeUnit.MILLISECONDS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查配置信息
|
||||||
|
*/
|
||||||
|
public void checkConfigInfo() {
|
||||||
|
int listenerSize = cacheMap.size();
|
||||||
|
double perTaskConfigSize = 3000D;
|
||||||
|
int longingTaskCount = (int) Math.ceil(listenerSize / perTaskConfigSize);
|
||||||
|
|
||||||
|
if (longingTaskCount > currentLongingTaskCount) {
|
||||||
|
for (int i = (int) currentLongingTaskCount; i < longingTaskCount; i++) {
|
||||||
|
executorService.execute(new LongPollingRunnable(i));
|
||||||
|
}
|
||||||
|
currentLongingTaskCount = longingTaskCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 长轮训任务
|
||||||
|
*/
|
||||||
|
class LongPollingRunnable implements Runnable {
|
||||||
|
|
||||||
|
private final int taskId;
|
||||||
|
|
||||||
|
public LongPollingRunnable(int taskId) {
|
||||||
|
this.taskId = taskId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
List<CacheData> cacheDataList = new ArrayList();
|
||||||
|
|
||||||
|
List<String> changedTpIds = checkUpdateTpIds(cacheDataList);
|
||||||
|
if (!CollectionUtils.isEmpty(cacheDataList)) {
|
||||||
|
log.info("[dynamic threadPool] tpIds changed :: {}", changedTpIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (String each : changedTpIds) {
|
||||||
|
String[] keys = each.split(",");
|
||||||
|
String namespace = keys[0];
|
||||||
|
String itemId = keys[1];
|
||||||
|
String tpId = keys[2];
|
||||||
|
|
||||||
|
try {
|
||||||
|
String content = getServerConfig(namespace, itemId, tpId, 3000L);
|
||||||
|
CacheData cacheData = cacheMap.get(tpId);
|
||||||
|
cacheData.setContent(content);
|
||||||
|
cacheDataList.add(cacheData);
|
||||||
|
log.info("[data-received] namespace :: {}, itemId :: {}, tpId :: {}, md5 :: {}, content :: {}",
|
||||||
|
namespace, itemId, tpId, cacheData.getMd5(), content);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (CacheData each : cacheDataList) {
|
||||||
|
each.checkListenerMd5();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查修改的线程池 ID
|
||||||
|
*
|
||||||
|
* @param cacheDataList
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public List<String> checkUpdateTpIds(List<CacheData> cacheDataList) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getServerConfig(String namespace, String itemId, String tpId, long readTimeout) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CacheData 添加 Listener
|
||||||
|
*
|
||||||
|
* @param tpId
|
||||||
|
* @param listeners
|
||||||
|
*/
|
||||||
|
public void addTenantListeners(String tpId, List<? extends Listener> listeners) {
|
||||||
|
CacheData cacheData = addCacheDataIfAbsent(tpId);
|
||||||
|
for (Listener listener : listeners) {
|
||||||
|
cacheData.addListener(listener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CacheData 不存在则添加
|
||||||
|
*
|
||||||
|
* @param tpId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public CacheData addCacheDataIfAbsent(String tpId) {
|
||||||
|
CacheData cacheData = cacheMap.get(tpId);
|
||||||
|
if (cacheData != null) {
|
||||||
|
return cacheData;
|
||||||
|
}
|
||||||
|
|
||||||
|
cacheData = new CacheData(tpId);
|
||||||
|
CacheData lastCacheData = cacheMap.putIfAbsent(tpId, cacheData);
|
||||||
|
|
||||||
|
return lastCacheData;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,26 @@
|
|||||||
|
package io.dynamic.threadpool.starter.listener;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听器
|
||||||
|
*
|
||||||
|
* @author chen.ma
|
||||||
|
* @date 2021/6/22 20:20
|
||||||
|
*/
|
||||||
|
public interface Listener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取执行器
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Executor getExecutor();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接受配置信息
|
||||||
|
*
|
||||||
|
* @param configInfo
|
||||||
|
*/
|
||||||
|
void receiveConfigInfo(String configInfo);
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
package io.dynamic.threadpool.starter.operation;
|
||||||
|
|
||||||
|
import io.dynamic.threadpool.starter.core.ConfigService;
|
||||||
|
import io.dynamic.threadpool.starter.listener.Listener;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ThreadPoolOperation.
|
||||||
|
*
|
||||||
|
* @author chen.ma
|
||||||
|
* @date 2021/6/22 20:25
|
||||||
|
*/
|
||||||
|
public class ThreadPoolOperation {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigService configService;
|
||||||
|
|
||||||
|
public Listener subscribeConfig(String tpId, Executor executor, ThreadPoolSubscribeCallback threadPoolSubscribeCallback) {
|
||||||
|
Listener configListener = new Listener() {
|
||||||
|
@Override
|
||||||
|
public void receiveConfigInfo(String config) {
|
||||||
|
threadPoolSubscribeCallback.callback(tpId, config);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Executor getExecutor() {
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
configService.addListener(tpId, configListener);
|
||||||
|
|
||||||
|
return configListener;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package io.dynamic.threadpool.starter.operation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ThreadPoolSubscribeCallback.
|
||||||
|
*
|
||||||
|
* @author chen.ma
|
||||||
|
* @date 2021/6/22 20:26
|
||||||
|
*/
|
||||||
|
public interface ThreadPoolSubscribeCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回调函数
|
||||||
|
*
|
||||||
|
* @param tpId
|
||||||
|
* @param config
|
||||||
|
*/
|
||||||
|
void callback(String tpId, String config);
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package io.dynamic.threadpool.starter.wrap;
|
||||||
|
|
||||||
|
import io.dynamic.threadpool.starter.listener.Listener;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 监听包装
|
||||||
|
*
|
||||||
|
* @author chen.ma
|
||||||
|
* @date 2021/6/22 17:47
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ManagerListenerWrap {
|
||||||
|
|
||||||
|
final Listener listener;
|
||||||
|
|
||||||
|
String lastCallMd5;
|
||||||
|
|
||||||
|
public ManagerListenerWrap(String md5, Listener listener) {
|
||||||
|
this.lastCallMd5 = md5;
|
||||||
|
this.listener = listener;
|
||||||
|
}
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -0,0 +1,5 @@
|
|||||||
|
spring:
|
||||||
|
threadpool:
|
||||||
|
dynamic:
|
||||||
|
namespace: common
|
||||||
|
itemId: message-center
|
Loading…
Reference in new issue