简介
我们使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。
线程池可以使线程复用,就是执行完一个任务,并不被销毁,而是可以继续执行其他的任务
看完本章你将会知道
构建出一个线程池,使用异步操作线程完成任务
配置文件
pom
<?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.boot</groupId>
<artifactId>demo-thread-pool</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>demo-thread-pool</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.6.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</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
项目结构图
image.pngTaskPoolConfig
package com.boot.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
public class TaskPoolConfig {
@Bean("selfpool")
public Executor selfpool() {
ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
pool.setCorePoolSize(10); //核心线程数10:线程池创建时候初始化的线程数
pool.setMaxPoolSize(20); //最大线程数20:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
pool.setQueueCapacity(200);//缓冲队列200:用来缓冲执行任务的队列
pool.setKeepAliveSeconds(60);//允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
pool.setThreadNamePrefix("selfpool-");//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
pool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); //线程池对拒绝任务的处理策略:这里采用了CallerRunsPolicy策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
return pool;
}
}
Task
@Slf4j
@Component
public class Task {
public static Random random = new Random();
@Async("selfpool")
public void doTaskOne() throws Exception {
log.info("开始做任务一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(5000));
long end = System.currentTimeMillis();
log.info("完成任务一,耗时:{}", (end - start));
}
@Async("selfpool")
public void doTaskTwo() throws Exception {
log.info("开始做任务二");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(5000));
long end = System.currentTimeMillis();
log.info("完成任务二,耗时:{}", (end - start));
}
@Async("selfpool")
public void doTaskThree() throws Exception {
log.info("开始做任务三");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(5000));
long end = System.currentTimeMillis();
log.info("完成任务三,耗时:{}", (end - start));
}
}
DemoThreadPoolApplication
@SpringBootApplication
@EnableAsync
public class DemoThreadPoolApplication {
public static void main(String[] args) {
SpringApplication.run(DemoThreadPoolApplication.class, args);
}
}
DemoThreadPoolApplicationTests
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoThreadPoolApplicationTests {
@Autowired
private Task task;
@Test
public void test() throws Exception {
task.doTaskOne();
task.doTaskTwo();
task.doTaskThree();
Thread.currentThread().join();
//在多线程编程中,Thread.CurrentThread 表示获取当前正在运行的线程,join方法是阻塞当前调用线程,直到某线程完全执行才调用线程才继续执行,如果获取的当前线程是主线程,调用Join方法,会是怎样的呢
//阻塞住,因为线程无法结束
}
}
image.png
网友评论