
业务场景
假设我们需要做一个设备实时监控的程序, 有如下业务需求:
- 在系统启动时, 根据设备个数生成对应的线程
- 线程内部轮询, 实现设备的初始化和状态监控
本文重点介绍如何在Spring Boot中使用多线程, 后续会加更使用状态模式实现设备在不同状态下的各种操作
方案
先来列举下面试经常会问的问题, Java中有几种实现线程的方式:
- 继承Thread类
- 实现Runnable接口
- 使用Callable和FutureTask
- 使用线程池
- Spring Boot中的@Async
本文着重讲述如何最后一种, 其实Spring Boot也是集前几者之大成
在这里多说一句, 很多新人小伙伴们经常会在写代码之前不好好调研
比如知道了可以用线程池, 就火急火燎的写了一个自己的实现类, 但伴随着开发深入, 设计到线程的管理/守护线程等就会出现很多预料之外的问题
所以推荐各位和我一样处理学习期的兄弟们, 先确定自己的技术栈(例如MyBatis还是JPA), 之后在技术栈的基础上去搜索有无相关的工具/实现/轮子, 写代码之前一定要思考代码
Spring Boot的多线程就是最好的例子, 起码在笔者看来, 它很优雅且完美
开启多线程
第一步, 在启动类增加@EnableAsync注解:
@EnableAsync
public class DeviceApplication {
/**
* main方法
*
* @param args 参数
*/
public static void main(String[] args) {
SpringApplication.run(DeviceApplication.class, args);
}
}
复制代码
第二步, 在需要多线程处理的类或方法上增加@Async注解:
public class ConnectorService {
private static final int INTERVAL = 5000;
/**
* 设备链接方法
*
* @param device 设备实体
*/
@Async
public void connect(Device device) {
device.setState(new OffLineState(device));
try {
while (true) {
device.getState().heartBeat();
Thread.sleep(INTERVAL);
}
} catch (InterruptedException e) {
LOGGER.error(String.format("设备[%s]监控线程意外中断", device.getId()), e);
Thread.currentThread().interrupt();
}
}
}
复制代码
如此这般, 在使用默认配置的情况下, 我们就实现了connect方法的多线程处理, 每次对connect方法的调用都会启动新的线程
具体的配置参数网上一搜一大堆, 不再赘述
需要注意的坑
@Async注解和事务一样, 在类内部调用会出现注解失效的情况, 需要格外注意
原创文章,作者:睿达君,如若转载,请注明出处:https://zrrd.net.cn/1548.html