线程池配置
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Slf4j
@EnableAsync
@Configuration
public class ThreadPoolConfig {
private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
private static final int COUR_SIZE = CPU_COUNT * 2;
private static final int MAX_COUR_SIZE = COUR_SIZE * 4;
@Bean("threadExecutor")
public ThreadPoolTaskExecutor threadExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = null;
try {
threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
int i = Runtime.getRuntime().availableProcessors();
threadPoolTaskExecutor.setCorePoolSize(COUR_SIZE);
threadPoolTaskExecutor.setMaxPoolSize(MAX_COUR_SIZE);
threadPoolTaskExecutor.setQueueCapacity(MAX_COUR_SIZE * 2 * 10);
threadPoolTaskExecutor.setKeepAliveSeconds(60);
threadPoolTaskExecutor.setThreadNamePrefix("threadExecutor-");
threadPoolTaskExecutor.setRejectedExecutionHandler(new SelfRejectedExecutionHandler());
threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);
threadPoolTaskExecutor.initialize();
log.info("初始化线程池成功");
} catch (Exception e) {
log.error("初始化线程池失败: {}", e.getMessage());
}
return threadPoolTaskExecutor;
}
}
线程任务存取工具类
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
@Slf4j
@Component
public class ThreadReader {
private static final BlockingQueue<Runnable> BLOCKING_QUEUE = new LinkedBlockingQueue<>();
@Autowired
@Qualifier("threadExecutor")
private ThreadPoolTaskExecutor threadExecutor;
public static void put(Runnable runnable) {
try {
BLOCKING_QUEUE.put(runnable);
} catch (InterruptedException e) {
log.error("ThreadReader.put异常:{}", e.getMessage());
}
}
public void take() {
if (CollectionUtils.isEmpty(BLOCKING_QUEUE)) {
return;
}
try {
Runnable runnable = BLOCKING_QUEUE.take();
log.info("取出当前线程池没来得及执行的任务, runnable:{}", runnable);
threadExecutor.execute(runnable);
} catch (InterruptedException e) {
log.error("ThreadReader.take异常:{}", e.getMessage());
}
}
}
自定义线程池的拒绝策略
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadPoolExecutor;
public class SelfRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable runnable, ThreadPoolExecutor executor) {
if (null != runnable) {
ThreadReader.put(runnable);
}
}
}
重新执行未执行的任务
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
@Slf4j
@Component
public class CustomizeScheduler implements ApplicationListener<ContextRefreshedEvent> {
@Autowired
private ThreadReader threadReader;
@Override
public void onApplicationEvent(ContextRefreshedEvent event) {
ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("scheduledExecutor-pool-%d")
.setUncaughtExceptionHandler((thread, throwable) -> log.error("ThreadPool {} got exception", thread, throwable)).build();
ScheduledExecutorService scheduledExecutor = new ScheduledThreadPoolExecutor(1, threadFactory, new SelfRejectedExecutionHandler());
scheduledExecutor.scheduleAtFixedRate(() -> threadReader.take(), 1, 1000, TimeUnit.MILLISECONDS);
}
}