Spring 与 JDK 线程池的简单使用示例详解
作者:羁客%
1.配置自定义共享线程池(Spring线程池)
@Configuration @EnableAsync public class ThreadPoolConfig{ //主要任务的调度,计划执行 @Bean("taskScheduler") public Executor createScheduler(){ // 创建一个线程池对象 ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler(); // 定义一个线程池大小 scheduler.setPoolSize(100); // 线程池名的前缀 scheduler.setThreadNamePrefix("taskScheduler-"); // 设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean scheduler.setWaitForTasksToCompleteOnShutdown(true); // 设置线程池中任务的等待时间,如果超过这个时候还没有销毁就强制销毁,以确保应用最后能够被关闭,而不是阻塞住 scheduler.setAwaitTerminationSeconds(60); // 线程池对拒绝任务的处理策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务 scheduler.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); return scheduler; } //主要任务的执行 @Bean("taskExecutor") public Executor createExecutor(){ // 创建一个线程池对象 ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); //核心线程池大小 executor.setCorePoolSize(10); //最大线程数 executor.setMaxPoolSize(30); //队列容量 executor.setQueueCapacity(100); //活跃时间 executor.setKeepAliveSeconds(60); //线程名字前缀 executor.setThreadNamePrefix("taskExecutor-"); // 设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean executor.setWaitForTasksToCompleteOnShutdown(true); // 线程池对拒绝任务的处理策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务 executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); return executor; } }
2.编写执行任务对象与具体任务逻辑方法
@Component public class TaskComponent{ @Async("taskExecutor") public void doTaskExecutor() { System.out.println("任务开始执行!!!"); //具体的执行任务 //。。。。。。。 } // //有返回值(ObjectVo为自己定义的返回类型) //@Async("taskExecutor") //public Future<ObjectVo> doTaskExecutor() { // System.out.println("任务开始执行!!!"); // //具体的执行任务 // //。。。。。。。 // ObjectVo result=new ObjectVo(); // return new AsyncResult<>(result); //} @Async("taskScheduler") public void doTaskScheduler() { System.out.println("任务开始调度!!!"); //具体的调度任务 //。。。。。。。 } // //有返回值(ObjectVo为自己定义的返回类型) //@Async("taskScheduler") //public Future<ObjectVo> doTaskScheduler() { // System.out.println("任务开始调度!!!"); // //具体的调度任务 // //。。。。。。。 // ObjectVo result=new ObjectVo(); // return new AsyncResult<>(result); //} }
3.调用任务方法(在哪调用都可以,根据自己业务需求在合适的地方调用即可)
@Service public class UserServiceImpl implements UserService{ @Autowired private TaskComponent taskComponent; //测试任务执行与调用 @SneakyThrows @Override public void testTask(){ //没有返回值 taskComponent.doTaskExecutor(); taskComponent.doTaskScheduler(); //有返回值 //Future<ObjectVo> executorResult = taskComponent.doTaskExecutor(); //Future<ObjectVo> schedulerResult = taskComponent.doTaskScheduler(); //System.out.println(executorResult.get()); //System.out.println(schedulerResult.get()); } }
===============Executors结构========jdk自带线程池==========
1.任务(Runnable,Callable)
2.任务的执行(Executor,ExecutorService 接口,ThreadPoolExecutor,ScheduledThreadExecutor实现类)
3.计算结果(返回结果 Future接口,FutureTask实现类)
===============Executors现成的线程池========jdk自带线程池====
1 Executors.FixedThreadPool 核心数=容纳的最大线程数=N
无界队列(当队列过多时,会造成无限循环)
2 Executors.CachedThreadPool 容纳的最大线程数=无界
主线程提交任务的速度高于 maximumPoolSize中线程处理任务的速度时 CachedThreadPool将会不断的创建新的线程,
在极端情况下,
CachedThreadPool会因为创建过多线程而耗尽CPU和内存资源
3 Executors.SingleThreadExecutor 核心数=容纳的最大线程数=1 始终保持只有一个线程在执行
无界队列(当队列过多时,会造成无限循环)
===============自定义Executors===========jdk自带线程池====================
ExecuteService threadPool = new ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler);
//设置线程池的前缀
ThreadFactory threadFactory = new ThreadFactoryBuilder()
.setNameFormat("trhead-pool-%d").build();
//设置决绝策略
RejectedExecutionHandler:
AbortPolicy:抛出RejectedExecutionException
CallerRunsPolicy:直接在execute方法的调用线程中运行被拒绝的任务。
DiscardOldestPolicy:放弃最旧的未处理请求,重试execute。
DiscardPolicy:丢弃被拒绝的任务。
================处理流程===================jdk 与 spring =====================
1.核心线程池是否在执行任务,不在执行就选一条线程执行,否则查看核心线程池是否已满
2.核心线程池是否满,不满则创建一条线程执行,否值查看队列是否已满
3.队列是否满,队列不满加入队列,否则查看线程池是否已满
4.线程池是否已满,线程池不满创建一条线程池,否则根据决绝策略处理
# 1.当一个任务被提交到线程池时,首先查看线程池的核心线程是否都在执行任务,否就选择一条线程执行任务,是就执行第二步。
# 2.查看核心线程池是否已满,不满就创建一条线程执行任务,否则执行第三步。
# 3.查看任务队列是否已满,不满就将任务存储在任务队列中,否则执行第四步。
# 4.查看线程池是否已满,不满就创建一条线程执行任务,否则就按照策略(拒绝策略)处理无法执行的任务。
到此这篇关于Spring 与 JDK 线程池的简单使用的文章就介绍到这了,更多相关Spring 与 JDK 线程池内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!