測試代碼
pom.xml
:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.2</version>
</parent>
<packaging>jar</packaging>
<groupId>com.kaven</groupId>
<artifactId>springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot</name>
<description>springboot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
啟動類:
package com.kaven.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(SpringbootApplication.class);
application.run(args);
}
}
異步任務
在上下文中沒有執行器
bean
的情況下,
Spring Boot
會自動配置
ThreadPoolTaskExecutor
,使其具有合理的預設值,這些預設值可以自動關聯到異步任務執行(
@EnableSync
)和
Spring MVC
異步請求處理。
線程池預設使用
8
個核心線程,它們可以根據負載進行動态擴充和收縮。可以使用
spring.task.execution
命名空間修改這些預設設定。
public static class Pool {
/**
* 隊列容量
* Integer.MAX_VALUE表示無限容量(隊列無界),是以會忽略maxSize屬性
*/
private int queueCapacity = Integer.MAX_VALUE;
/**
* 核心線程數
*/
private int coreSize = 8;
/**
* 允許的最大線程數
* 如果任務正在填滿隊列,則線程池可以擴充到該大小以适應負載
* 如果隊列無界則忽略該屬性
*/
private int maxSize = Integer.MAX_VALUE;
/**
* 是否允許核心線程逾時
* 這可以實作線程池的動态擴充和收縮
*/
private boolean allowCoreThreadTimeout = true;
/**
* 線程在終止之前可能保持空閑的時間限制
*/
private Duration keepAlive = Duration.ofSeconds(60);
}
application.properties
:
spring.task.execution.pool.max-size=16
spring.task.execution.pool.queue-capacity=100
spring.task.execution.pool.keep-alive=10s
上面的配置會将線程池更改為使用有界隊列,以便當隊列已滿(
100
個任務)時,線程池增加到
16
個線程。當線程空閑
10
秒(而不是預設情況下的
60
秒)後會被回收。
開啟異步任務功能:
package com.kaven.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
@SpringBootApplication
@EnableAsync
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(SpringbootApplication.class);
application.run(args);
}
}
異步任務:
package com.kaven.springboot.task;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class AsyncTask {
@Async
public void service(){
try {
// 模拟異步任務處理
Thread.sleep(5 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(System.currentTimeMillis());
System.out.println("異步任務處理結束");
}
}
接口:
package com.kaven.springboot.controller;
import com.kaven.springboot.task.AsyncTask;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class TaskController {
@Resource
private AsyncTask asyncTask;
@GetMapping("/async")
public long async() {
asyncTask.service();
return System.currentTimeMillis();
}
}
使用
Postman
進行測試。
1644482662434
1644482667447
異步任務處理結束
很顯然請求響應時
AsyncTask
類的
service
方法還沒有執行完,符合異步任務的預期。
定時任務
如果需要與定時任務的執行相關聯(例如使用
@EnableScheduling
),
Spring Boot
會自動配置
ThreadPoolTaskScheduler
。線程池預設使用一個線程,可以使用
spring.task.scheduling
命名空間修改其設定。
application.properties
:
spring.task.scheduling.thread-name-prefix=scheduling-
spring.task.scheduling.pool.size=2
-
:用于建立新線程的名稱字首。spring.task.scheduling.thread-name-prefix
-
:允許的最大線程數。spring.task.scheduling.pool.size
開啟定時任務功能:
package com.kaven.springboot;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication
@EnableScheduling
public class SpringbootApplication {
public static void main(String[] args) {
SpringApplication application = new SpringApplication(SpringbootApplication.class);
application.run(args);
}
}
定時任務:
package com.kaven.springboot.task;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduleTask {
@Scheduled(cron = "*/10 * * * * *")
public void service(){
System.out.println(System.currentTimeMillis());
System.out.println("定時任務處理結束");
}
}
*/10 * * * * *
表示每
10
秒鐘執行一次任務,
cron
時間表達式的介紹可以參考以下部落格:
- cron時間表達式簡介
- Cron表達式詳解
接口:
package com.kaven.springboot.controller;
import com.kaven.springboot.task.ScheduleTask;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@RestController
public class TaskController {
@Resource
private ScheduleTask scheduleTask;
@GetMapping("/schedule")
public String schedule() {
scheduleTask.service();
return "定時任務啟動成功";
}
}
使用
Postman
進行測試。
控制台輸出如下圖所示: