前言
最近项目当中有需求,要进行异步的处理,需要使用到线程池,很久没有使用到线程池了,一来是做JAVAweb开发基本上很少用到异步处理,二来是发现有的老项目里面,线程和线程池的使用比较混乱,有好几个线程池,有的线程池是通过spring管理的,有的是自己创建的,然后有的地方是直接创建的线程。所以这里记录下自己在项目当中如何优雅的使用线程池!避免项目当中到处都是线程池!!!【白嫖资料】
SpringBoot整合ThreadPoolTaskExecutor线程池
ThreadPoolExecutor:这个是JAVA自己实现的线程池执行类,基本上创建线程池都是通过这个类进行的创建!
ThreadPoolTaskExecutor :这个是springboot基于ThreadPoolExecutor实现的一个线程池执行类。
In the absence of an Executor bean in the context, Spring Boot
auto-configures a ThreadPoolTaskExecutor with sensible defaults that
can be automatically associated to asynchronous task execution
(@EnableAsync) and Spring MVC asynchronous request processing.
在springboot当中,根据 官方文档的说明,如果没有配置线程池的话,springboot会自动配置一个ThreadPoolTaskExecutor 线程池到bean当中,我们只需要按照他的方式调用就可以了!!!
使用springboot默认的线程池
既然springboot有默认的线程池,说明我们可以很简单的进行调用
方式一:通过@Async注解调用
第一步:在Application启动类上面加上@EnableAsync
@SpringBootApplication
@EnableAsync
public class ThreadpoolApplication {
public static void main(String[] args) {
SpringApplication.run(ThreadpoolApplication.class, args);
}
}
第二步:在需要异步执行的方法上加上@Async注解
@Service
public class AsyncTest {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Async
public void hello(String name){
//这里使用logger 方便查看执行的线程是什么
logger.info("异步线程启动 started."+name);
}
}
第三步:测试类进行测试验证
@Autowired
AsyncTest asyncTest;
@Test
void contextLoads() throws InterruptedException {
asyncTest.hello("afsasfasf");
//一定要休眠 不然主线程关闭了,子线程还没有启动
Thread.sleep(1000);
}
查看打印的日志:
INFO 2276 — [ main] c.h.s.t.t.ThreadpoolApplicationTests : Started
ThreadpoolApplicationTests in 3.003 seconds (JVM running for 5.342)
INFO 2276 — [ task-1] c.h.s.threadpool.threadpool.AsyncTest : 异步线程启动
started.afsasfasf
可以清楚的看到新开了一个task-1的线程执行任务。验证成功!!!
方式二:直接调用ThreadPoolTaskExecutor
修改上面测试类,直接注入ThreadPoolTaskExecutor
@SpringBootTest
class ThreadPoolApplicationTests {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
AsyncTest asyncTest;
@Autowired
ThreadPoolTaskExecutor threadPoolTaskExecutor;
@Test
void contextLoads() throws InterruptedException {
asyncTest.hello("async注解创建");
threadPoolTaskExecutor.submit(new Thread(()->{
logger.info("threadPoolTaskExecutor 创建线程");
}));
//一定要休眠 不然主线程关闭了,子线程还没有启动
Thread.sleep(1000);
}
}
查看打印的日志发现都成功创建线程!!!:
INFO 12360 — [ task-2] c.h.s.t.t.ThreadpoolApplicationTests :
threadPoolTaskExecutor 创建线程 INFO 12360 — [ task-1]
c.h.s.threadpool.threadpool.AsyncTest : 异步线程启动 started.async注解创建
备注1:如果只使用ThreadPoolTaskExecutor, 是可以不用在