本节要点
- 学会多线程的应用场景
- 多线程实现的方式
- 学会如何使用线程池
- 学会再SpringBoot里怎么使用多线程
1、什么是多线程
[明白单线程]
单线程是指一个程序(进程)从头到尾只有一条唯一的执行路径。这条路径被称为主线程(Main Thread)。

你可以把它想象成一条单车道:所有的车辆(任务)都必须在这条车道上排成一队,顺序通过。前一辆车不开走,后一辆就只能等着

多线程(Multithreading) 就是指一个进程同时运行多个线程来完成不同的任务。


2、什么场景用多线程?
-
“打造灵敏的用户界面”
为了防止主线程阻塞,并行执行多个任务,相互不影响
-
cpu资源足够的情况下,有效利用cpu资源,多并发处理业务

3、如何使用多线程
1. 继承 Thread 类
这是最基本的方法,通过继承 Thread 类并重写 run() 方法。
class MyThread extends Thread {
@Override
public void run() {
// 线程执行的代码
System.out.println("线程运行: " + Thread.currentThread().getName());
}
}
...
xxx.start();
2. 实现 Runnable 接口
lass MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行的代码
System.out.println("Runnable运行: " + Thread.currentThread().getName());
}
}
线程资源建议通过线程池创建,尽量不要在应用中自行显式创建线程。
3.使用线程池
- Executors (不建议使用)
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10);
// 提交任务
fixedThreadPool.submit(() -> {
// 你的任务代码
System.out.println("Task executed by " + Thread.currentThread().getName());
});
// 关闭线程池
fixedThreadPool.shutdown();
- ThreadPoolExecutor(建议使用)
线程池不要使用 Executors 去创建,用 ThreadPoolExecutor 的方式。
4、ThreadPoolExecutor参数
ThreadPoolExecutor threadPool = new ThreadPoolExecutor(
//核心线程数
corePoolSize:10,
//临时线程数
maximumPoolSize:20,
//临时线程超时时间
keepAliveTime:60L,
TimeUnit.SECONDS,
//任务队列
new ArrayBlockingQueue<Runnable>(capacity:10),
//创建线程的工厂
Executors.defaultThreadFactory(),
//拒绝策略
new ThreadPoolExecutor.AbortPolicy()
);
5、ThreadPoolExecutor原理

-
有界队列
说明:
核心线程 -> 放队列->开临时线程 ->拒绝策略
new ArrayBlockingQueue<Runnable>(capacity:10), -
无界队列
说明:永远不会创建超过核心线程数的线程,因为队列永远不会满。
核心线程 ->放队列->等oom
new LinkedBlockingQueue<>() -
同步移交
说明:不会放到队列里面
核心线程->开临时线程->拒绝策略
new SynchronousQueue<>()
6、拒绝策略
1. AbortPolicy(中止策略)
- 含义:默认策略。直接抛出
RejectedExecutionException异常,阻止系统正常运行 - 特点:最严格的策略,确保任务不会丢失,但需要调用者处理异常
- 适用场景:关键任务系统,不能容忍任务丢失的情况
2. CallerRunsPolicy(调用者运行策略)
- 含义:将任务回退给调用者线程执行(即提交任务的线程自己执行)
- 特点:不会丢弃任务,但会降低新任务提交速度,起到简单的反馈调节作用
- 适用场景:需要保证所有任务都能被执行,且可以接受提交速度变慢的场景
3. DiscardPolicy(丢弃策略)
- 含义:静默丢弃无法处理的任务,不抛异常,也不做任何通知
- 特点:最简单粗暴的策略,可能造成任务丢失而不自知
- 适用场景:无关紧要的任务,允许丢弃一些请求的场景
4. DiscardOldestPolicy(丢弃最老策略)
- 含义:丢弃队列中最老的(最先进入队列的)任务,然后尝试重新提交当前任务
- 特点:用新任务替换旧任务,可能丢失重要但排队久的任务
- 适用场景:新任务比旧任务更重要的场景,如实时性要求高的系统
4、如何使用
package com.daiwei.springmvc.uti;
import java.util.concurrent.*;
public class ThreadTest {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(5);
ThreadPoolExecutor executor1 = new ThreadPoolExecutor(5,
10,
6000,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(5),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy());
executor1.execute(()->{
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("子线程");
});
System.out.println("主线程");
}
}
spring mvc里使用
1、加一个配置(纳入spring容器管理)
package com.daiwei.springmvc.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.concurrent.*;
@Configuration
public class ThreadPoolConfig {
@Bean("customThreadPool1")
public ThreadPoolExecutor customThreadPool() {
int corePoolSize = Runtime.getRuntime().availableProcessors();
int maxPoolSize = corePoolSize * 2;
int queueCapacity = 100;
return new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(queueCapacity),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
@Bean("customThreadPool2")
public ThreadPoolExecutor customThreadPool() {
int corePoolSize = Runtime.getRuntime().availableProcessors();
int maxPoolSize = corePoolSize * 2;
int queueCapacity = 100;
return new ThreadPoolExecutor(
corePoolSize,
maxPoolSize,
60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(queueCapacity),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.CallerRunsPolicy()
);
}
}
serviceImpl里注入
...
@Autowired
ThreadPoolExecutor threadPoolExecutor;
@RequestMapping("/register")
public String register(@RequestParam("name") String name, @RequestParam("pwd") String pwd) {
...
threadPoolExecutor.execute(()->{
System.out.println("==============hello="+name+"==pwd="+pwd);
});
...
return "success";
}
spring Config加入加入整个配置
package com.daiwei.springmvc.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.*;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.sql.DataSource;
@Configuration
@ComponentScan({"com.daiwei.springmvc.service","com.daiwei.springmvc.dao"})
@Import({MybatisConfig.class,JdbcConfig.class,ThreadPoolConfig.class})//@Import 注解会将指定的类注册到IOC中
@EnableAspectJAutoProxy
public class SpringConfig implements WebMvcConfigurer {
}
6、spring boot里如何使用
ThreadPoolTaskExecutor
- 增加一个配置类
@Configuration
@EnableAsync
public class ThreadPoolConfig {
@Bean("threadPoolTaskExecutor1")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程数
executor.setCorePoolSize(5);
//最大线程数
executor.setMaxPoolSize(10);
//线程池所使用的缓冲队列
executor.setQueueCapacity(100);
//等待时间超过60秒后线程将被回收
executor.setKeepAliveSeconds(60);
//线程拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
executor.initialize();
return executor;
}
@Bean("threadPoolTaskExecutor2")
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程数
executor.setCorePoolSize(5);
//最大线程数
executor.setMaxPoolSize(10);
//线程池所使用的缓冲队列
executor.setQueueCapacity(100);
//等待时间超过60秒后线程将被回收
executor.setKeepAliveSeconds(60);
//线程拒绝策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardPolicy());
executor.initialize();
return executor;
}
}
-
service 加上注解
@Async("threadPoolTaskExecutor1") @Async("threadPoolTaskExecutor2")
评论