springboot 异步调用有必要配置线程池吗,springboot创建线程池
00-1010 I. Spring Boot任务线程池II。自定义线程池III。优雅地关闭线程池
00-1010线程池的作用
防止资源占用无限扩展,节省资源创建和销毁的时间,在高并发环境下不断分配新的资源,可能导致系统资源耗尽。所以为了避免这个问题,我们为异步任务设计了一个线程池。当然,如果没有配置线程池,springboot会自动在bean中配置一个ThreadPoolTaskExecutor线程池。
#弹簧芯线数量。task . execution . pool . core-size=8 # spring的最大线程数。task . execution . pool . max-size=16 #空闲线程生存期spring。task . execution . pool . keep-alive=60s #允许核心线程超时spring。task . execution . pool . allow-core-thread-time out=true #线程队列数量spring。task . execution . pool . queue-capacity=100 #线程关闭等待春天。task . execution . shut down . await-termination=false spring . task . execution . shut down . await-termination-period=# Thread name prefix spring . task . execution . Thread-name-prefix=task-将上述配置添加到springboot配置文件中,即可实现ThreadPoolTaskExecutor线程池。
00-1010有时候,我们想把系统中的一类任务放到一个线程池中,另一类任务放到另一个线程池中,这样就很难使用Spring Boot自带的任务线程池了。下面是定制线程池的方法。
创建一个线程池配置类TaskConfiguration并配置一个任务线程池对象taskExecutor。
@ configuration public class task configuration { @ Bean( task Executor )public Executor task Executor(){ threadpooltasktexecutor Executor=new threadpooltasktexecutor();executor . setcorepoolsize(10);executor . setmaxpoolsize(20);executor . setqueuecapacity(200);executor . setkeepaliveseconds(60);executor . setthreadname prefix( task executor-);executor . setrejectedexecutionhandler(new caller run policy());返回执行人;}}
上面,我们通过使用ThreadPoolTaskExecutor创建了一个线程池,并设置了以下参数:
线程池属性attribute的作用上面的代码设置了核心线程数的初始值。创建CorePoolSize线程池时初始化的线程数,最小线程数为10,最大线程数为MaxPoolSize,线程池中的最大线程数仅在缓冲区队列满后。只有那些申请数量大于核心线程20的线程缓冲任务队列QueueCapacity。用于缓冲执行任务的队列200允许线程的空闲时间超过核心线程之外的线程的空闲时间。空闲时间达到后,未使用的线程将被销毁60秒。ThreadNamePrefix可以用来定位处理任务所在的线程池。taskExecutor-线程池对任务的拒绝策略。当线程池饱和运行或线程池处于关闭的临界状态时,有四种预定义的拒绝任务的策略:
被拒绝任务的处理程序AbortPolicy将抛出RejectedExecutionException。CallerRunsPolicy是被拒绝任务的处理程序,它直接在execute方法的调用线程中运行被拒绝的任务。DiscardOldestPolicy是被拒绝任务的处理程序,它丢弃最早的未处理请求,然后重试执行。默认情况下,丢弃策略是被拒绝任务的处理程序
它将丢弃被拒绝的任务。创建 AsyncExecutorTask类,三个任务的配置和 AsyncTask 一样,不同的是 @Async 注解需要指定前面配置的 线程池的名称 taskExecutor。
@Componentpublic class AsyncExecutorTask extends AbstractTask { @Async("taskExecutor") public Future<String> doTaskOneCallback() throws Exception { super.doTaskOne(); System.out.println("任务一,当前线程:" + Thread.currentThread().getName()); return new AsyncResult<>("任务一完成"); } @Async("taskExecutor") public Future<String> doTaskTwoCallback() throws Exception { super.doTaskTwo(); System.out.println("任务二,当前线程:" + Thread.currentThread().getName()); return new AsyncResult<>("任务二完成"); } @Async("taskExecutor") public Future<String> doTaskThreeCallback() throws Exception { super.doTaskThree(); System.out.println("任务三,当前线程:" + Thread.currentThread().getName()); return new AsyncResult<>("任务三完成"); }}
在 单元测试 用例中,注入 AsyncExecutorTask 对象,并在测试用例中执行 doTaskOne(),doTaskTwo(),doTaskThree() 三个方法。
@SpringBootTestpublic class AsyncExecutorTaskTest { @Autowired private AsyncExecutorTask task; @Test public void testAsyncExecutorTask() throws Exception { task.doTaskOneCallback(); task.doTaskTwoCallback(); task.doTaskThreeCallback(); sleep(30 * 1000L); }}
执行一下上述的 单元测试,可以看到如下结果:
开始做任务一开始做任务三开始做任务二完成任务二,耗时:3905毫秒任务二,当前线程:taskExecutor-2完成任务一,耗时:6184毫秒任务一,当前线程:taskExecutor-1完成任务三,耗时:9737毫秒任务三,当前线程:taskExecutor-3
执行上面的单元测试,观察到 任务线程池 的 线程池名的前缀 被打印,说明 线程池 成功执行 异步任务!
三、优雅地关闭线程池
由于在应用关闭的时候异步任务还在执行,导致类似 数据库连接池 这样的对象一并被 销毁了,当 异步任务 中对 数据库 进行操作就会出错。
解决方案如下,重新设置线程池配置对象,新增线程池 setWaitForTasksToCompleteOnShutdown() 和 setAwaitTerminationSeconds() 配置:
@Bean("taskExecutor")public Executor taskExecutor() { ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler(); executor.setPoolSize(20); executor.setThreadNamePrefix("taskExecutor-"); executor.setWaitForTasksToCompleteOnShutdown(true); executor.setAwaitTerminationSeconds(60); return executor;}
setWaitForTasksToCompleteOnShutdown(true): 该方法用来设置 线程池关闭 的时候 等待 所有任务都完成后,再继续 销毁 其他的 Bean,这样这些 异步任务 的 销毁 就会先于 数据库连接池对象 的销毁。setAwaitTerminationSeconds(60): 该方法用来设置线程池中 任务的等待时间,如果超过这个时间还没有销毁就 强制销毁,以确保应用最后能够被关闭,而不是阻塞住。异步任务** 的 销毁 就会先于 数据库连接池对象 的销毁。
setAwaitTerminationSeconds(60): 该方法用来设置线程池中 任务的等待时间,如果超过这个时间还没有销毁就 强制销毁,以确保应用最后能够被关闭,而不是阻塞住。到此这篇关于springboot为异步任务规划自定义线程池的实现的文章就介绍到这了,更多相关springboot异步自定义线程池内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。