We often useThreadPoolExecutor Thread pool service provided,springboot The framework [email protected] 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 combat source code

The source code of this actual battle can be found in myGitHub 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 isthreadpooldemoserver, As shown in the red box below:


Combing the practical steps

The steps of this actual battle are as follows:
1. Establishspringboot engineering;
2. EstablishService Interface and implementation of layer;
3. Establishcontroller, Develop onehttp Service interface, It will callservice Layer services;
4. Create configuration for thread pool;
5. takeService Layer service asynchronization, In this way, every call will be submitted to the thread pool for asynchronous execution;
6. extendThreadPoolTaskExecutor, When submitting tasks to the thread pool, you can observe the current situation of the thread pool;

Establishspringboot engineering

useIntelliJ IDEA Create aspringboot Ofweb engineeringthreadpooldemoserver,pom.xml The contents are 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>
EstablishService Interface and implementation of layer

Create aservice Layer interfaceAsyncService, as follows:
public interface AsyncService { /** * Perform asynchronous tasks */ void executeAsync(); }
CorrespondingAsyncServiceImpl, The following are achieved:
@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 A second.;

Establishcontroller

Create acontroller byHello, It defines ahttp Interface, The thing to do is callService 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"); // callservice Layer task asyncService.executeAsync(); logger.info("end submit"
);return "success"; } }

thus, We've made onehttp Requested services, What we do in it is actually synchronous, Next, we start to configurespringboot Thread pool service for, takeservice Everything the layer does is submitted to the thread pool for processing;

springboot Thread pool configuration for


Create a configuration classExecutorConfig, Used to define how to create aThreadPoolTaskExecutor, To [email protected] [email protected] These two notes, Indicates that this is a configuration class, And it is the configuration class of thread pool, As shown below:
@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: Whenpool Already achievedmax 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 isasyncServiceExecutor, It will be used soon;

takeService Layer service asynchronization

openAsyncServiceImpl.java, stayexecuteAsync Add comments on [email protected](“asyncServiceExecutor”)
,asyncServiceExecutor FrontExecutorConfig.java Method name in, IndicateexecuteAsync The thread pool entered by method isasyncServiceExecutor 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"); }
Validation effect

* Take thisspringboot Run up(pom.xml Executed under the foldermvn spring-boot:run);
* Enter in browser:http://localhost:8080 <http://localhost:8080>;
* In browserF5 Button refresh several times quickly;
* stayspringboot 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 seecontroller The execution thread of is”nio-8080-exec-8”, This istomcat Execution thread of, andservice 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;

extendThreadPoolTaskExecutor


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 aThreadPoolTaskExecutor Subclasses, 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, Number of active threads, The queue size is printed out, Then?Override Parent classexecute,submit Other methods, Call inshowThreadPoolInfo 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;

modifyExecutorConfig.java OfasyncServiceExecutor Method, takeThreadPoolTaskExecutor executor
= new ThreadPoolTaskExecutor() Change toThreadPoolTaskExecutor executor = new
VisiableThreadPoolTaskExecutor(), As shown below:
@Bean public Executor asyncServiceExecutor() { logger.info("start
asyncServiceExecutor"); // UseVisiableThreadPoolTaskExecutor
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: Whenpool Already achievedmax 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 againhttp://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, What is called issubmit(Callable task)
This method, Currently submitted101 Task, It's done87 individual, Currently there are5 Threads processing tasks, Left9 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;