Springboot自帶線程池的實現(xiàn)
一: ThreadPoolTaskExecuto
1 ThreadPoolTaskExecutor線程池:
ThreadPoolTaskExecutor是Spring基于java本身的線程池ThreadPoolExecutor做的二次封裝,主要目的還是為了更加方便的在spring框架體系中使用線程池, 是Spring中默認的線程池
2 使用ThreadPoolTaskExecutor注入bean到ioc中
配置文件形式,Spring會自動配置
## 默認線程池配置,ThreadPoolTaskExecutor # 核心線程數(shù) spring.task.execution.pool.core-size=8 # 最大線程數(shù) spring.task.execution.pool.max-size=16 # 空閑線程存活時間 spring.task.execution.pool.keep-alive=60s # 是否允許核心線程超時 spring.task.execution.pool.allow-core-thread-timeout=true # 線程隊列數(shù)量 spring.task.execution.pool.queue-capacity=100 # 線程關閉等待 spring.task.execution.shutdown.await-termination=false spring.task.execution.shutdown.await-termination-period= # 線程名稱前綴 spring.task.execution.thread-name-prefix=demo_Thread
配置形式:
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledFuture; //@Configuration public class ThreadConfig { @Value("${task.maxPoolSize}") private int maxPoolSize; //todo 其他的相關配置都可以通過配置文件中注入 @Bean("ThreadPoolTaskExecutor") public Executor myAsync() { final ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setMaxPoolSize(maxPoolSize); //todo 其他參數(shù)設置 //初始化 executor.initialize(); return executor; } }
3 創(chuàng)建線程后全部從ioc中獲取線程池子
4 線程池處理流程:
(1) 查看核心線程池是否已滿,不滿就創(chuàng)建一條線程執(zhí)行任務,核心線程數(shù)量已滿就查看任務隊列是否已滿不滿就將線程存儲在任務隊列中任務隊列已滿,就查看最大線程數(shù)量,不滿就創(chuàng)建線程執(zhí)行任務,已滿就按照拒絕策略執(zhí)行
(2) 拒絕策略:
- CallerRunsPolicy():原來的線程執(zhí)行
- AbortPolicy():直接拋出異常
- DiscardPolicy():直接丟棄
- DiscardOldestPolicy():丟棄隊列中最老的任
二: ThreadPoolTaskScheduler
1 ThreadPoolTaskScheduler 定時調度任務線程池,處理異步任務
2 使用方式: 注入 ThreadPoolTaskScheduler的bean
(1) 配置文件形式:..
(2) 配置類形式:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ScheduledFuture; @Configuration public class ThreadPoolTaskSchedulerConfig { @Bean public ThreadPoolTaskScheduler threadPoolTaskScheduler() { final ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler(); //設置等待任務在關機時l候完成 threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true); //設置等待時間為60s threadPoolTaskScheduler.setAwaitTerminationSeconds(60); return threadPoolTaskScheduler; } }
3 使用ThreadPoolTaskScheduler定時任務
做普通線程池使用:
- submit(callable),需要執(zhí)行結果
- submit(runnable),不需要執(zhí)行結果
(1) 定時任務
添加任務內容Runnable,設置執(zhí)行周期Trigger/Date,Trigger表達式百度即可
schedule(Runnable task,Trigger) schedule(Runnable task,Date)
(2) 指定間隔時間執(zhí)行一次任務,時間間隔是前一次任務完成到下一次任務開始,單位毫秒
scheduleWithFixedDelay(Runnable task,long delay)
(3) 固定頻率執(zhí)行任務,在任務開始后間隔一段時間執(zhí)行新的任務,如果上次任務么執(zhí)行完成,則等待上次任務執(zhí)行完成后執(zhí)行下次任務
scheduleAtFixedRate(Runnable task,long delay)
(4) 定時任務取消:
設置定時任務存儲的集合,定時任務執(zhí)行的結果為ScheduledFuture<?>,將該對象存儲到集合,通過在集合中獲取ScheduledFuture<?>對象.cancel(true)取消定時任務
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.scheduling.support.CronTrigger; import org.springframework.stereotype.Service; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.concurrent.*; @Service public class SchedulerService { @Autowired ThreadPoolTaskScheduler scheduler; /** * 常規(guī)線程池使用 */ public void tesScheduler1() throws ExecutionException, InterruptedException { //無返回值 final Future<?> demo_scheduler1 = scheduler.submit(new Runnable() { @Override public void run() { System.out.println("demo runnable scheduler"); } }); //無返回值 final Future<?> demo_scheduler2 = scheduler.submit(new Callable<Object>() { @Override public Object call() throws Exception { System.out.println("demo callable scheduler"); return "callable"; } }); System.out.println("result:" + demo_scheduler2.get()); } /** * 定時任務 */ public void tesScheduler2() throws ParseException { //CronTrigger表達式百度即可 scheduler.schedule(() -> { System.out.println("定時任務"); }, new CronTrigger("0/1****?")); //創(chuàng)建指定時間的日期 final Date date = new Date(2023, 3, 26, 21, 35); final DateFormat format = new SimpleDateFormat(); final Date parse = format.parse("2023-03-26-21-26"); scheduler.schedule(() -> { System.out.println(new Date()); }, parse); } /** * 指定時間間隔執(zhí)行任務,上次任務結束到下次任務開始的時間間隔 */ public void tesScheduler3() { scheduler.scheduleWithFixedDelay(() -> { //todo }, 300L); } /** * 固定頻率執(zhí)行任務,在固定一段時間后便會執(zhí)行下次任務, * 如果時間到了上次任務還沒執(zhí)行完畢則等待, * 直到上一次任務執(zhí)行完畢后立馬執(zhí)行下次任務 */ public void tesScheduler4() { scheduler.scheduleAtFixedRate(new FutureTask<String>(new Callable<String>() { @Override public String call() throws Exception { return null; } }), 200); } //取消定時任務隊列 public static ConcurrentMap<String, ScheduledFuture> map = new ConcurrentHashMap<>(); public void startTask(String k1) { map.compute(k1, (k, v) -> { if (map.containsKey(k)) return v; map.put(k, v); return v; }); } }
三 @Scheduled實現(xiàn)定時任務,注解開啟定時任務
1 使用@EnableScheduled開啟支持
2 @Scheduled標注方法
(1)@Scheduled(fixedDelay=5000)延遲執(zhí)行,5s后執(zhí)行
(2)@Scheduled(fixedRate=5000)定時執(zhí)行,每隔五秒就進行執(zhí)行
(3)@Scheduled(corn="002**?") 自定義執(zhí)行,corn表達式百度,常用這種執(zhí)行方式,corn="002**?"每天凌晨兩點開始執(zhí)行定時任務
3 注意@Scheduled開啟的任務是單線程的,容易阻塞
(1) 在ioc中注入ThreadPoolTaskScheduler,則Scheduled就使用ThreadPoolTaskScheduler線程池,可以解決單線程阻塞問題
(2) @Scheduled和@Async注解開啟定時任務,在@Async("pool")中指定線程池,若是沒有指定線程池會使用Spring的SimpleAsyncTaskExecutor線程池,這個線程池每次都會增加一個線程去執(zhí)行任務,效率低下
四:Spring中的異步任務
1 @EnableAsync開啟異步支持
2 @Async開啟異步任務,指定線程池
注意:@Scheduled和@Async注解開啟定時任務,在@Async("pool")中指定線程池,若是沒有指定線程池會使用Spring的SimpleAsyncTaskExecutor線程池,這個線程池每次都會增加一個線程去執(zhí)行任務,效率低下但是@Async單獨開啟異步任務,則使用的是默認的線程池,建議根據(jù)需求自定義線程池
注意:@Async的返回值只能為void或Future, 調用方和@Async不能在一個類中,否則不走aop;
import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class AsyncService { @Async public void showThreadName1() { //默認線程池 System.out.println(Thread.currentThread().getName()); } @Async("myPool")//指定線程池 public void showThreadName2() { System.out.println(Thread.currentThread().getName()); } }
五:獻上一顆自java自定義線程池:
@Bean("myPool") public Executor executor(){ return new ThreadPoolExecutor(// 自定義一個線程池 1, // coreSize 2, // maxSize 60, // 60s TimeUnit.SECONDS, new ArrayBlockingQueue<>(3) // 有界隊列,容量是3個 , Executors.defaultThreadFactory() , new ThreadPoolExecutor.AbortPolicy()); }
java自帶的線程池,緩存,固定數(shù)量的,單線程的,定時的,,,,六七種,后面續(xù)上
到此這篇關于Springboot自帶線程池的實現(xiàn)的文章就介紹到這了,更多相關Springboot自帶線程池內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
SpringBoot?@RestControllerAdvice注解對返回值統(tǒng)一封裝的處理方法
這篇文章主要介紹了SpringBoot?@RestControllerAdvice注解對返回值統(tǒng)一封裝,使用@RestControllerAdvice對響應進行增強,本文結合實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-09-09Spring?Cloud?Sleuth?和?Zipkin?進行分布式跟蹤使用小結
分布式跟蹤是一種機制,我們可以使用它跟蹤整個分布式系統(tǒng)中的特定請求,分布式跟蹤允許您跟蹤分布式系統(tǒng)中的請求,本文給大家介紹Spring?Cloud?Sleuth?和?Zipkin?進行分布式跟蹤使用小結,感興趣的朋友一起看看吧2022-03-03Mybatis實現(xiàn)查詢相冊數(shù)據(jù)列表流程講解
這篇文章主要介紹了Mybatis實現(xiàn)查詢相冊數(shù)據(jù)列表流程,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習吧2022-12-12