实体类
public class ExecutorDto {
private String id;
private String name;
private String description;
private Date createTime;
public ExecutorDto(String id, String name, String description, Date createTime) {
this.id = id;
this.name = name;
this.description = description;
this.createTime = createTime;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(getClass().getSimpleName());
sb.append(" [");
sb.append(", id=").append(id);
sb.append(", name=").append(name);
sb.append(", description=").append(description);
sb.append(", createTime=").append(createTime);
sb.append("]");
return sb.toString();
}
}
继承Runnable接口 实现线程方法
public abstract class ExtendedRunnable implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(ExtendedRunnable.class);
protected abstract void start() throws InterruptedException, Exception;
private ExecutorDto executorDto;
public ExtendedRunnable(ExecutorDto executorDto) {
this.executorDto = executorDto;
}
public ExecutorDto getExecutorDto() {
return executorDto;
}
public void setExecutorDto(ExecutorDto executorDto) {
this.executorDto = executorDto;
}
@Override
public void run() {
if (StringUtils.isEmpty(executorDto.getId())){
try {
throw new Exception("请命名启动线程的id!");
} catch (Exception e) {
logger.error("线程Id为空",e);
}
return;
}
if (ThreadPoolExecutorConfig.RUNNING_MAP.containsKey(executorDto.getId())
&& ThreadPoolExecutorConfig.INFO_MAP.containsKey(executorDto.getId())){
try {
throw new Exception("请勿重复提交相同的线程id!");
} catch (Exception e) {
logger.error("线程Id重复",e);
}
return;
}
try {
beforeExecute(executorDto, Thread.currentThread());
this.start();
} catch (InterruptedException e){
logger.error("线程InterruptedException:"+executorDto.toString(),e);
} catch (Exception e) {
logger.error("线程未知Exception:"+executorDto.toString(),e);
} finally {
afterExecute(executorDto);
}
}
protected void beforeExecute(ExecutorDto dto,Thread t){
ThreadPoolExecutorConfig.RUNNING_MAP.put(dto.getId(), t);
ThreadPoolExecutorConfig.INFO_MAP.put(dto.getId(),dto);
logger.info("beforeExecute>> RUNING_MAP.size():"+ThreadPoolExecutorConfig.RUNNING_MAP.size()+", INFO_MAP.size():"+ThreadPoolExecutorConfig.INFO_MAP.size()+", 线程info"+dto.toString());
}
protected void afterExecute(ExecutorDto dto){
ThreadPoolExecutorConfig.RUNNING_MAP.remove(dto.getId());
ThreadPoolExecutorConfig.INFO_MAP.remove(dto.getId());
logger.info("afterExecute>> RUNING_MAP.size():"+ThreadPoolExecutorConfig.RUNNING_MAP.size()+", INFO_MAP.size():"+ThreadPoolExecutorConfig.INFO_MAP.size()+", 线程info"+dto.toString());
}
}
继承Runnable接口 实现 Latch 线程方法
public abstract class ExtendedLatchRunnable implements Runnable {
private static final Logger logger = LoggerFactory.getLogger(ExtendedLatchRunnable.class);
private CountDownLatch latch = null;
protected abstract void start() throws InterruptedException, Exception;
private ExecutorDto executorDto;
public ExtendedLatchRunnable(ExecutorDto executorDto, CountDownLatch latch) {
this.executorDto = executorDto;
this.latch = latch;
}
public ExecutorDto getExecutorDto() {
return executorDto;
}
public void setExecutorDto(ExecutorDto executorDto) {
this.executorDto = executorDto;
}
@Override
public void run() {
if (StringUtils.isEmpty(executorDto.getId())){
try {
throw new Exception("请命名启动线程的id!");
} catch (Exception e) {
logger.error("线程Id为空",e);
}
return;
}
if (ThreadPoolExecutorConfig.RUNNING_MAP.containsKey(executorDto.getId())
&& ThreadPoolExecutorConfig.INFO_MAP.containsKey(executorDto.getId())){
try {
throw new Exception("请勿重复提交相同的线程id!");
} catch (Exception e) {
logger.error("线程Id重复",e);
}
return;
}
try {
beforeExecute(executorDto, Thread.currentThread());
this.start();
} catch (InterruptedException e){
logger.error("线程InterruptedException:"+executorDto.toString(),e);
} catch (Exception e) {
logger.error("线程未知Exception:"+executorDto.toString(),e);
} finally {
afterExecute(executorDto);
}
}
protected void beforeExecute(ExecutorDto dto,Thread t){
ThreadPoolExecutorConfig.RUNNING_MAP.put(dto.getId(), t);
ThreadPoolExecutorConfig.INFO_MAP.put(dto.getId(),dto);
logger.info("beforeExecute>> RUNING_MAP.size():"+ThreadPoolExecutorConfig.RUNNING_MAP.size()+", INFO_MAP.size():"+ThreadPoolExecutorConfig.INFO_MAP.size()+", 线程info"+dto.toString());
}
protected void afterExecute(ExecutorDto dto){
ThreadPoolExecutorConfig.RUNNING_MAP.remove(dto.getId());
ThreadPoolExecutorConfig.INFO_MAP.remove(dto.getId());
logger.info("afterExecute>> RUNING_MAP.size():"+ThreadPoolExecutorConfig.RUNNING_MAP.size()+", INFO_MAP.size():"+ThreadPoolExecutorConfig.INFO_MAP.size()+", 线程info"+dto.toString());
logger.info("latch size is " + latch.getCount());
latch.countDown();
}
}
线程配置类
@Configuration
@EnableAsync
public class ThreadPoolExecutorConfig {
private static Logger logger = LoggerFactory.getLogger(ThreadPoolExecutorConfig.class);
public static ConcurrentHashMap<String, Thread> RUNNING_MAP = new ConcurrentHashMap<>();
public static HashMap<String, ExecutorDto> INFO_MAP = new HashMap<>();
@Value("${task.executor.pool.size}")
private Integer taskExecutorPoolSize = 5;
@Value("${task.executor.queue.size}")
private Integer taskExecutorQueueSize = 200;
@Bean
public Executor pushExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(taskExecutorPoolSize);
executor.setMaxPoolSize(taskExecutorPoolSize);
executor.setKeepAliveSeconds(30);
executor.setQueueCapacity(taskExecutorQueueSize);
executor.setThreadNamePrefix("push-");
System.out.println("taskExecutorPoolSize:" + taskExecutorPoolSize + ";taskExecutorQueueSize" + taskExecutorQueueSize);
executor.setRejectedExecutionHandler((r, t) -> {
try {
String id = DateUtils.formatDate(new Date(), "yyyyMMddHHmmss")+"-"+ IdGen.randomBase62(6);
logger.warn("任务id:"+id+",线程池 pushExecutor 已经超出最大线程数,队列阻塞,等待可用空间再继续!目前队列数量:"
+ t.getQueue().size()+"个,时间:"+new Date());
t.getQueue().put(r);
logger.warn("任务id:"+id+",线程池 pushExecutor 阻塞已经解除!");
} catch (InterruptedException e) {
logger.error("线程池 pushExecutor 阻塞异常:", e);
}
});
executor.initialize();
return executor;
}
}
使用样例
@Autowired
@Qualifier(value = "commandExecutor")
private Executor pushExecutor;
pushExecutor.execute(new ExtendedRunnable(new ExecutorDto(id,"","",new Date())) {
@Override
protected void start() throws InterruptedException, Exception {
try {
long start = System.currentTimeMillis();
logger.info("开始...线程id【{}】,开始时间【{}】",id,start);
long end = System.currentTimeMillis();
long consume = end - start;
logger.info("结束...线程id【{}】,结束时间【{}】,耗时【{}】毫秒",id,end,consume);
} catch ( Exception e) {
logger.error(e.getClass().toString());
throw e;
}
}
});