概念: 线程池由任务队列和工作线程组成,它可以重用线程来避免创建的开销,
在任务过多时,通过排队避免创建过多线程来减少资源消耗和竞争。
ThreadPool 参数说明:
// Java线程池的完整构造函数
public ThreadPoolExecutor(
int corePoolSize, // 线程池长期维持的线程数,即使线程处于Idle状态,也不会回收。
int maximumPoolSize, // 线程池最大活跃线程数量
long keepAliveTime, TimeUnit unit, // 超过核心线程数量时,空闲线程空闲时间
// 超过这个时间线程会被回收。
BlockingQueue<Runnable> workQueue, // 任务的排队队列
ThreadFactory threadFactory, // 新线程的产生方式
RejectedExecutionHandler handler) // 拒绝策略
..
拒绝策略:
/**
* AbortPolicy 抛出RejectedExecutionException
* DiscardPolicy 什么也不做,直接忽略
* DiscardOldestPolicy 丢弃执行队列中最老的任务,尝试为当前提交的任务腾出位置
* CallerRunsPolicy 直接由提交任务者执行这个任务
* */
使用ThreadPoolExecutor构造函数创建线程池:
简单演示,参数自己定
int corePoolSize = Runtime.getRuntime().availableProcessors() *2; //CPU的数量
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>(512);//任务队列,512
RejectedExecutionHandler policy = new ThreadPoolExecutor.DiscardPolicy();//拒绝策略
ExecutorService executorService = new ThreadPoolExecutor(corePoolSize, corePoolSize,0, TimeUnit.SECONDS, queue,policy);
Executors 快捷创建线程池
//定长线程池,可控制线程最大并发数,超出的线程会在队列中等待
//无限的LinkedBlockingQueue阻塞队列,存活时间永远不会超时
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
//控制不当容易 OOM(内存溢出)
//可缓存线程池 , 如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程线程池里的每一个线程代码结束后,并不会死亡,而是再次回到线程池中成为空闲状态
//核心池是 0。 最大池设置为Integer.MAX_VALUE (2147483647), 默认的超时时间为1分钟。,同步移交方式。
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
//定长线程池,支持定时及周期性任务执行
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
//例:
scheduledThreadPool.schedule(() ->System.out.println("索引:"+index+"延迟3秒..."+Thread.currentThread().getName()),3,TimeUnit.SECONDS);
scheduledThreadPool.scheduleAtFixedRate(() -> System.out.println("索引:"+index+"延迟3秒后,每3秒执行一次"+Thread.currentThread().getName()),3,3,TimeUnit.SECONDS);
//一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行
//无限的LinkedBlockingQueue阻塞队列
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
正确使用方式 ↓
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
* @author hexiaoshu
*/
@Configuration
@EnableAsync
public class TaskExecutePool {
@Bean("taskAsyncPool")
public Executor myTaskAsyncPool() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(100);
executor.setKeepAliveSeconds(1000);
executor.setThreadNamePrefix("checkFileThread-");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是由调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
return executor;
}
}
//接口层
void checkAccountFile(EpayCompanyMerch epayCompanyMerch,String savePath);
//@Async 调用时,开启一个线程处理。
@Override
@Async("taskAsyncPool")
public void checkAccountFile(EpayCompanyMerch epayCompanyMerch, String savePath){
getFileTask(epayCompanyMerch,savePath);
}