Springboot自帶線程池的實(shí)現(xiàn)
一: ThreadPoolTaskExecuto
1 ThreadPoolTaskExecutor線程池:
ThreadPoolTaskExecutor是Spring基于java本身的線程池ThreadPoolExecutor做的二次封裝,主要目的還是為了更加方便的在spring框架體系中使用線程池, 是Spring中默認(rèn)的線程池
2 使用ThreadPoolTaskExecutor注入bean到ioc中
配置文件形式,Spring會(huì)自動(dòng)配置
## 默認(rèn)線程池配置,ThreadPoolTaskExecutor # 核心線程數(shù) spring.task.execution.pool.core-size=8 # 最大線程數(shù) spring.task.execution.pool.max-size=16 # 空閑線程存活時(shí)間 spring.task.execution.pool.keep-alive=60s # 是否允許核心線程超時(shí) spring.task.execution.pool.allow-core-thread-timeout=true # 線程隊(duì)列數(shù)量 spring.task.execution.pool.queue-capacity=100 # 線程關(guān)閉等待 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 其他的相關(guān)配置都可以通過(guò)配置文件中注入
@Bean("ThreadPoolTaskExecutor")
public Executor myAsync() {
final ThreadPoolTaskExecutor executor =
new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(maxPoolSize);
//todo 其他參數(shù)設(shè)置
//初始化
executor.initialize();
return executor;
}
}3 創(chuàng)建線程后全部從ioc中獲取線程池子
4 線程池處理流程:
(1) 查看核心線程池是否已滿,不滿就創(chuàng)建一條線程執(zhí)行任務(wù),核心線程數(shù)量已滿就查看任務(wù)隊(duì)列是否已滿不滿就將線程存儲(chǔ)在任務(wù)隊(duì)列中任務(wù)隊(duì)列已滿,就查看最大線程數(shù)量,不滿就創(chuàng)建線程執(zhí)行任務(wù),已滿就按照拒絕策略執(zhí)行
(2) 拒絕策略:
- CallerRunsPolicy():原來(lái)的線程執(zhí)行
- AbortPolicy():直接拋出異常
- DiscardPolicy():直接丟棄
- DiscardOldestPolicy():丟棄隊(duì)列中最老的任
二: ThreadPoolTaskScheduler
1 ThreadPoolTaskScheduler 定時(shí)調(diào)度任務(wù)線程池,處理異步任務(wù)
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();
//設(shè)置等待任務(wù)在關(guān)機(jī)時(shí)l候完成
threadPoolTaskScheduler.setWaitForTasksToCompleteOnShutdown(true);
//設(shè)置等待時(shí)間為60s
threadPoolTaskScheduler.setAwaitTerminationSeconds(60);
return threadPoolTaskScheduler;
}
}3 使用ThreadPoolTaskScheduler定時(shí)任務(wù)
做普通線程池使用:
- submit(callable),需要執(zhí)行結(jié)果
- submit(runnable),不需要執(zhí)行結(jié)果
(1) 定時(shí)任務(wù)
添加任務(wù)內(nèi)容Runnable,設(shè)置執(zhí)行周期Trigger/Date,Trigger表達(dá)式百度即可
schedule(Runnable task,Trigger) schedule(Runnable task,Date)
(2) 指定間隔時(shí)間執(zhí)行一次任務(wù),時(shí)間間隔是前一次任務(wù)完成到下一次任務(wù)開(kāi)始,單位毫秒
scheduleWithFixedDelay(Runnable task,long delay)
(3) 固定頻率執(zhí)行任務(wù),在任務(wù)開(kāi)始后間隔一段時(shí)間執(zhí)行新的任務(wù),如果上次任務(wù)么執(zhí)行完成,則等待上次任務(wù)執(zhí)行完成后執(zhí)行下次任務(wù)
scheduleAtFixedRate(Runnable task,long delay)
(4) 定時(shí)任務(wù)取消:
設(shè)置定時(shí)任務(wù)存儲(chǔ)的集合,定時(shí)任務(wù)執(zhí)行的結(jié)果為ScheduledFuture<?>,將該對(duì)象存儲(chǔ)到集合,通過(guò)在集合中獲取ScheduledFuture<?>對(duì)象.cancel(true)取消定時(shí)任務(wù)
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 {
//無(wú)返回值
final Future<?> demo_scheduler1 = scheduler.submit(new Runnable() {
@Override
public void run() {
System.out.println("demo runnable scheduler");
}
});
//無(wú)返回值
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());
}
/**
* 定時(shí)任務(wù)
*/
public void tesScheduler2() throws ParseException {
//CronTrigger表達(dá)式百度即可
scheduler.schedule(() -> {
System.out.println("定時(shí)任務(wù)");
}, new CronTrigger("0/1****?"));
//創(chuàng)建指定時(shí)間的日期
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);
}
/**
* 指定時(shí)間間隔執(zhí)行任務(wù),上次任務(wù)結(jié)束到下次任務(wù)開(kāi)始的時(shí)間間隔
*/
public void tesScheduler3() {
scheduler.scheduleWithFixedDelay(() -> {
//todo
}, 300L);
}
/**
* 固定頻率執(zhí)行任務(wù),在固定一段時(shí)間后便會(huì)執(zhí)行下次任務(wù),
* 如果時(shí)間到了上次任務(wù)還沒(méi)執(zhí)行完畢則等待,
* 直到上一次任務(wù)執(zhí)行完畢后立馬執(zhí)行下次任務(wù)
*/
public void tesScheduler4() {
scheduler.scheduleAtFixedRate(new FutureTask<String>(new Callable<String>() {
@Override
public String call() throws Exception {
return null;
}
}),
200);
}
//取消定時(shí)任務(wù)隊(duì)列
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實(shí)現(xiàn)定時(shí)任務(wù),注解開(kāi)啟定時(shí)任務(wù)
1 使用@EnableScheduled開(kāi)啟支持
2 @Scheduled標(biāo)注方法
(1)@Scheduled(fixedDelay=5000)延遲執(zhí)行,5s后執(zhí)行
(2)@Scheduled(fixedRate=5000)定時(shí)執(zhí)行,每隔五秒就進(jìn)行執(zhí)行
(3)@Scheduled(corn="002**?") 自定義執(zhí)行,corn表達(dá)式百度,常用這種執(zhí)行方式,corn="002**?"每天凌晨?jī)牲c(diǎn)開(kāi)始執(zhí)行定時(shí)任務(wù)
3 注意@Scheduled開(kāi)啟的任務(wù)是單線程的,容易阻塞
(1) 在ioc中注入ThreadPoolTaskScheduler,則Scheduled就使用ThreadPoolTaskScheduler線程池,可以解決單線程阻塞問(wèn)題
(2) @Scheduled和@Async注解開(kāi)啟定時(shí)任務(wù),在@Async("pool")中指定線程池,若是沒(méi)有指定線程池會(huì)使用Spring的SimpleAsyncTaskExecutor線程池,這個(gè)線程池每次都會(huì)增加一個(gè)線程去執(zhí)行任務(wù),效率低下
四:Spring中的異步任務(wù)
1 @EnableAsync開(kāi)啟異步支持
2 @Async開(kāi)啟異步任務(wù),指定線程池
注意:@Scheduled和@Async注解開(kāi)啟定時(shí)任務(wù),在@Async("pool")中指定線程池,若是沒(méi)有指定線程池會(huì)使用Spring的SimpleAsyncTaskExecutor線程池,這個(gè)線程池每次都會(huì)增加一個(gè)線程去執(zhí)行任務(wù),效率低下但是@Async單獨(dú)開(kāi)啟異步任務(wù),則使用的是默認(rèn)的線程池,建議根據(jù)需求自定義線程池
注意:@Async的返回值只能為void或Future, 調(diào)用方和@Async不能在一個(gè)類中,否則不走aop;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@Service
public class AsyncService {
@Async
public void showThreadName1() {
//默認(rèn)線程池
System.out.println(Thread.currentThread().getName());
}
@Async("myPool")//指定線程池
public void showThreadName2() {
System.out.println(Thread.currentThread().getName());
}
}五:獻(xiàn)上一顆自java自定義線程池:
@Bean("myPool")
public Executor executor(){
return new ThreadPoolExecutor(// 自定義一個(gè)線程池
1, // coreSize
2, // maxSize
60, // 60s
TimeUnit.SECONDS, new ArrayBlockingQueue<>(3) // 有界隊(duì)列,容量是3個(gè)
, Executors.defaultThreadFactory()
, new ThreadPoolExecutor.AbortPolicy());
}java自帶的線程池,緩存,固定數(shù)量的,單線程的,定時(shí)的,,,,六七種,后面續(xù)上
到此這篇關(guān)于Springboot自帶線程池的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Springboot自帶線程池內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot?@RestControllerAdvice注解對(duì)返回值統(tǒng)一封裝的處理方法
這篇文章主要介紹了SpringBoot?@RestControllerAdvice注解對(duì)返回值統(tǒng)一封裝,使用@RestControllerAdvice對(duì)響應(yīng)進(jìn)行增強(qiáng),本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-09-09
mybatis通過(guò)if語(yǔ)句實(shí)現(xiàn)增刪改查操作
這篇文章主要介紹了mybatis通過(guò)if語(yǔ)句實(shí)現(xiàn)增刪改查操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-11-11
Java如何獲取對(duì)象屬性及對(duì)應(yīng)值
這篇文章主要介紹了Java如何獲取對(duì)象屬性及對(duì)應(yīng)值,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
SpringCloud啟動(dòng)失敗問(wèn)題匯總
這篇文章主要介紹了SpringCloud啟動(dòng)失敗問(wèn)題匯總,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
Spring?Cloud?Sleuth?和?Zipkin?進(jìn)行分布式跟蹤使用小結(jié)
分布式跟蹤是一種機(jī)制,我們可以使用它跟蹤整個(gè)分布式系統(tǒng)中的特定請(qǐng)求,分布式跟蹤允許您跟蹤分布式系統(tǒng)中的請(qǐng)求,本文給大家介紹Spring?Cloud?Sleuth?和?Zipkin?進(jìn)行分布式跟蹤使用小結(jié),感興趣的朋友一起看看吧2022-03-03
Mybatis實(shí)現(xiàn)查詢相冊(cè)數(shù)據(jù)列表流程講解
這篇文章主要介紹了Mybatis實(shí)現(xiàn)查詢相冊(cè)數(shù)據(jù)列表流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12
JAVA之讀取properties時(shí)路徑的注意問(wèn)題
這篇文章主要介紹了JAVA之讀取properties時(shí)路徑的注意問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
Java Socket編程(三) 服務(wù)器Sockets
Java Socket編程(三) 服務(wù)器Sockets...2006-12-12

