We often use ThreadPoolExecutor Thread pool service provided ,springboot The framework provides @Async annotation , Help us more easily submit business logic to thread pool for asynchronous execution , Today, we are going to experience the thread pool service ;

Address of this article :http://blog.csdn.net/boling_cavalry/article/details/79120268
<http://blog.csdn.net/boling_cavalry/article/details/79120268>

Actual combat environment

* windowns10;
* jdk1.8;
* springboot 1.5.9.RELEASE;
* development tool :IntelliJ IDEA;
Actual source code

The source code of this actual battle can be found in my GitHub download , address :[email protected]:zq2599/blog_demos.git, Project Home :
https://github.com/zq2599/blog_demos <https://github.com/zq2599/blog_demos>

There are many projects in it , The project used this time is threadpooldemoserver, As shown in the red box below :


Combing the practical steps

The steps of this actual battle are as follows :
1. establish springboot engineering ;
2. establish Service Interface and implementation of layer ;
3. establish controller, Develop a http Service interface , It will call service Layer services ;
4. Create configuration for thread pool ;
5. take Service Layer service asynchronization , In this way, every call will be submitted to the thread pool for asynchronous execution ;
6. extend ThreadPoolTaskExecutor, When submitting tasks to the thread pool, you can observe the current situation of the thread pool ;

establish springboot engineering

use IntelliJ IDEA Create a springboot Of web engineering threadpooldemoserver,pom.xml The content is as follows :
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.bolingcavalry</groupId> <
artifactId>threadpooldemoserver</artifactId> <version>0.0.1-SNAPSHOT</version> <
packaging>jar</packaging> <name>threadpooldemoserver</name> <description>Demo
project for Spring Boot</description> <parent> <groupId>org.springframework.boot
</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>
1.5.9.RELEASE</version> <relativePath/> <!-- lookup parent from repository -->
</parent> <properties> <project.build.sourceEncoding>UTF-8</
project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</
project.reporting.outputEncoding> <java.version>1.8</java.version> </properties>
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <
artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <
build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <
artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
</project>
establish Service Interface and implementation of layer

Create a service Layer interface AsyncService, as follows :
public interface AsyncService { /** * Perform asynchronous tasks */ void executeAsync(); }
Corresponding AsyncServiceImpl, The implementation is as follows :
@Service public class AsyncServiceImpl implements AsyncService { private static
final Logger logger = LoggerFactory.getLogger(AsyncServiceImpl.class); @Override
public void executeAsync() { logger.info("start executeAsync"); try{
Thread.sleep(1000); }catch(Exception e){ e.printStackTrace(); } logger.info(
"end executeAsync"); } }
It's very simple :sleep For a second ;

establish controller

Create a controller by Hello, It defines a http Interface , The thing to do is call Service Layer services , as follows :
@RestController public class Hello { private static final Logger logger =
LoggerFactory.getLogger(Hello.class);@Autowired private AsyncService
asyncService;@RequestMapping("/") public String submit(){ logger.info("start
submit"); // call service Layer tasks asyncService.executeAsync(); logger.info("end submit"
);return "success"; } }

thus , We've made one http Requested services , What we do in it is actually synchronous , Next, we start to configure springboot Thread pool service for , take service Everything the layer does is submitted to the thread pool for processing ;

springboot Thread pool configuration for


Create a configuration class ExecutorConfig, Used to define how to create a ThreadPoolTaskExecutor, To use @Configuration and @EnableAsync These two notes , Indicates that this is a configuration class , And it is the configuration class of thread pool , As follows :
@Configuration @EnableAsync public class ExecutorConfig { private static final
Logger logger = LoggerFactory.getLogger(ExecutorConfig.class);@Bean public
ExecutorasyncServiceExecutor() { logger.info("start asyncServiceExecutor");
ThreadPoolTaskExecutor executor =new ThreadPoolTaskExecutor(); // Configure the number of core threads
executor.setCorePoolSize(5); // Configure maximum threads executor.setMaxPoolSize(5); // Configure queue size
executor.setQueueCapacity(99999); // Configure the name prefix of threads in the thread pool executor.setThreadNamePrefix(
"async-service-"); // rejection-policy: When pool Reached max size When , How to handle new tasks //
CALLER_RUNS: Do not execute tasks in New Threads , Instead, there is the thread where the caller is running executor.setRejectedExecutionHandler(new
ThreadPoolExecutor.CallerRunsPolicy());// Perform initialization executor.initialize(); return
executor; } }
be careful , The method name above is asyncServiceExecutor, It will be used soon ;

take Service Layer service asynchronization

open AsyncServiceImpl.java, stay executeAsync Add comments on Methods @Async(“asyncServiceExecutor”)
,asyncServiceExecutor It's the front ExecutorConfig.java Method name in , indicate executeAsync The thread pool entered by method is asyncServiceExecutor Method created , as follows :
@Override @Async("asyncServiceExecutor") public void executeAsync() {
logger.info("start executeAsync"); try{ Thread.sleep(1000); }catch(Exception
e){ e.printStackTrace(); } logger.info("end executeAsync"); }
Verification effect

* Put this springboot Run it (pom.xml Executed under the folder mvn spring-boot:run);
* Enter in browser :http://localhost:8080 <http://localhost:8080>;
* In browser F5 Button refresh several times quickly ;
* stay springboot The log of the console is as follows : 2018-01-21 22:43:18.630 INFO 14824 --- [nio-8080
-exec-8] c.b.t.controller.Hello : start submit 2018-01-21 22:43:18.630 INFO
14824 --- [nio-8080-exec-8] c.b.t.controller.Hello : end submit 2018-01-21 22:43
:18.929 INFO 14824 --- [async-service-1] c.b.t.service.impl.AsyncServiceImpl :
end executeAsync2018-01-21 22:43:18.930 INFO 14824 --- [async-service-1] c.b.t
.service.impl.AsyncServiceImpl : start executeAsync 2018-01-21 22:43:19.005 INFO
14824 --- [async-service-2] c.b.t.service.impl.AsyncServiceImpl : end
executeAsync2018-01-21 22:43:19.006 INFO 14824 --- [async-service-2] c.b.t
.service.impl.AsyncServiceImpl : start executeAsync 2018-01-21 22:43:19.175 INFO
14824 --- [async-service-3] c.b.t.service.impl.AsyncServiceImpl : end
executeAsync2018-01-21 22:43:19.175 INFO 14824 --- [async-service-3] c.b.t
.service.impl.AsyncServiceImpl : start executeAsync 2018-01-21 22:43:19.326 INFO
14824 --- [async-service-4] c.b.t.service.impl.AsyncServiceImpl : end
executeAsync2018-01-21 22:43:19.495 INFO 14824 --- [async-service-5] c.b.t
.service.impl.AsyncServiceImpl : end executeAsync 2018-01-21 22:43:19.930 INFO
14824 --- [async-service-1] c.b.t.service.impl.AsyncServiceImpl : end
executeAsync2018-01-21 22:43:20.006 INFO 14824 --- [async-service-2] c.b.t
.service.impl.AsyncServiceImpl : end executeAsync 2018-01-21 22:43:20.191 INFO
14824 --- [async-service-3] c.b.t.service.impl.AsyncServiceImpl : end
executeAsync

As shown in the log above , We can see controller The execution thread of is ”nio-8080-exec-8”, This is tomcat Execution thread of , and service The log display thread name of the layer is “async-service-1”, Obviously, it has been executed in the thread pool we configured , And in every request ,controller The start and end logs of are printed continuously , Indicates that each request is responding quickly , The time-consuming operations are left to the threads in the thread pool to execute asynchronously ;

extend ThreadPoolTaskExecutor


Although we already use thread pool , But it's not clear what happened to the thread pool , How many threads are executing , How many are waiting in the queue ? Here I create a ThreadPoolTaskExecutor Subclass of , The current thread pool health will be printed out every time the thread is submitted , The code is as follows :
public class VisiableThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
private static final Logger logger =
LoggerFactory.getLogger(VisiableThreadPoolTaskExecutor.class);private void
showThreadPoolInfo(String prefix){ ThreadPoolExecutor threadPoolExecutor =
getThreadPoolExecutor();if(null==threadPoolExecutor){ return; } logger.info(
"{}, {},taskCount [{}], completedTaskCount [{}], activeCount [{}], queueSize
[{}]", this.getThreadNamePrefix(), prefix, threadPoolExecutor.getTaskCount(),
threadPoolExecutor.getCompletedTaskCount(),
threadPoolExecutor.getActiveCount(), threadPoolExecutor.getQueue().size()); }
@Override public void execute(Runnable task) { showThreadPoolInfo("1. do
execute"); super.execute(task); } @Override public void execute(Runnable task,
long startTimeout) { showThreadPoolInfo("2. do execute"); super.execute(task,
startTimeout); }@Override public Future<?> submit(Runnable task) {
showThreadPoolInfo("1. do submit"); return super.submit(task); } @Override
public <T> Future<T> submit(Callable<T> task) { showThreadPoolInfo("2. do
submit"); return super.submit(task); } @Override public ListenableFuture<?>
submitListenable(Runnable task) { showThreadPoolInfo("1. do submitListenable");
return super.submitListenable(task); } @Override public <T> ListenableFuture<T>
submitListenable(Callable<T> task) { showThreadPoolInfo("2. do submitListenable"
);return super.submitListenable(task); } }

As shown above ,showThreadPoolInfo Total number of tasks in method , Completed , Number of active threads , The queue size is printed out , then Override Of the parent class execute,submit Etc , Call in showThreadPoolInfo method , So every time a task is submitted to the thread pool , Will print the basic information of the current thread pool to the log ;

modify ExecutorConfig.java Of asyncServiceExecutor method , take ThreadPoolTaskExecutor executor
= new ThreadPoolTaskExecutor() Change to ThreadPoolTaskExecutor executor = new
VisiableThreadPoolTaskExecutor(), As follows :
@Bean public Executor asyncServiceExecutor() { logger.info("start
asyncServiceExecutor"); // use VisiableThreadPoolTaskExecutor
ThreadPoolTaskExecutor executor =new VisiableThreadPoolTaskExecutor(); // Configure the number of core threads
executor.setCorePoolSize(5); // Configure maximum threads executor.setMaxPoolSize(5); // Configure queue size
executor.setQueueCapacity(99999); // Configure the name prefix of threads in the thread pool executor.setThreadNamePrefix(
"async-service-"); // rejection-policy: When pool Reached max size When , How to handle new tasks //
CALLER_RUNS: Do not execute tasks in New Threads , Instead, there is the thread where the caller is running executor.setRejectedExecutionHandler(new
ThreadPoolExecutor.CallerRunsPolicy());// Perform initialization executor.initialize(); return
executor; }
Restart the project , Refresh the browser again and again http://localhost:8080 <http://localhost:8080>, The logs you see are as follows :
2018-01-21 23:04:56.113 INFO 15580 --- [nio-8080-exec-1] c.b.t.e
.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [99],
completedTaskCount [85], activeCount [5], queueSize [9] 2018-01-21 23:04:56.113
INFO15580 --- [nio-8080-exec-1] c.b.t.controller.Hello : end submit 2018-01-21
23:04:56.225 INFO 15580 --- [async-service-1] c.b.t.service.impl
.AsyncServiceImpl : end executeAsync 2018-01-21 23:04:56.225 INFO 15580 ---
[async-service-1] c.b.t.service.impl.AsyncServiceImpl : start executeAsync 2018-
01-21 23:04:56.240 INFO 15580 --- [nio-8080-exec-2] c.b.t.controller.Hello :
start submit2018-01-21 23:04:56.240 INFO 15580 --- [nio-8080-exec-2] c.b.t.e
.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [100],
completedTaskCount [86], activeCount [5], queueSize [9] 2018-01-21 23:04:56.240
INFO15580 --- [nio-8080-exec-2] c.b.t.controller.Hello : end submit 2018-01-21
23:04:56.298 INFO 15580 --- [async-service-2] c.b.t.service.impl
.AsyncServiceImpl : end executeAsync 2018-01-21 23:04:56.298 INFO 15580 ---
[async-service-2] c.b.t.service.impl.AsyncServiceImpl : start executeAsync 2018-
01-21 23:04:56.372 INFO 15580 --- [nio-8080-exec-3] c.b.t.controller.Hello :
start submit2018-01-21 23:04:56.373 INFO 15580 --- [nio-8080-exec-3] c.b.t.e
.VisiableThreadPoolTaskExecutor : async-service-, 2. do submit,taskCount [101],
completedTaskCount [87], activeCount [5], queueSize [9] 2018-01-21 23:04:56.373
INFO15580 --- [nio-8080-exec-3] c.b.t.controller.Hello : end submit 2018-01-21
23:04:56.444 INFO 15580 --- [async-service-3] c.b.t.service.impl
.AsyncServiceImpl : end executeAsync 2018-01-21 23:04:56.445 INFO 15580 ---
[async-service-3] c.b.t.service.impl.AsyncServiceImpl : start executeAsync
Note the line log :2. do submit,taskCount [101], completedTaskCount [87], activeCount
[5], queueSize [9]

This indicates that when the task is submitted to the thread pool , Called submit(Callable task)
This method , Currently submitted 101 Tasks , It's done 87 individual , There are currently 5 Threads processing tasks , Remaining 9 Tasks waiting in queue , The basic situation of thread pool is clear ;

thus ,springboot The implementation of thread pool service is completed , I hope it can help you to realize asynchronous service quickly in the project ;