在我们实际开发过程中,我们经常遇到一些场景:
1、如果调用方法超过1秒,就应该停止调用,不要一直阻塞下去,防止把本身的服务资源搞挂。
2、在不可预知可能出现死锁/死循环的代码,要加上时间的阀值,避免阻塞。
很多开源框架都会有超时响应的设置;如果是我们自己开发的服务,怎么能做到这点呢?
在jdk中有个future类,里面有获取等待超时的方法。
主要方法: cancel():取消任务 get():等待任务执行完成,并获取执行结果 get(long timeout, TimeUnit unit):在指定的时间内会等待任务执行,超时则抛异常。
本文不重点介绍future方法,可自行网补。
Google开源的Guava工具包,还是比较强大的;里面即包含了超时的控制。里面有个。
TimeLimiter 是个接口,下面有两个子类。
FakeTimeLimiter, 常用于debug时,限制时间超时调试。
SimpleTimeLimiter 常用于正式方法中,调用方法超时,即抛出异常。
这个类有2种方式实现超时的控制,代理模式和回调模式。
Guava采用的是JDK动态代理实现的AOP拦截,所以代理类必须实现一个接口。可以达到对类中所有的方法进行超时控制。
pom依赖
com.google.guava guava 29.0-jre
定义接口
定义了一个学生服务接口;
public interface StudentService {
/**
* 根据学生id 获取 学生姓名
* @param studentId
* @return
*/
String getStudentNameById(Integer studentId);
/**
* 根据学生id 获取 学生爱好
* @param studentId
* @return
*/
List getStudentHobbyById(Integer studentId);
}
接口实现
实现了根据id获取姓名,以及获取爱好;
@Service
public class StudentServiceImpl implements StudentService {
private static Logger logger = LoggerFactory.getLogger(StudentServiceImpl.class);
@Override
public String getStudentNameById(Integer studentId) {
try{
TimeUnit.SECONDS.sleep(3);
}catch (Exception e){
}
return "张三";
}
@Override
public List getStudentHobbyById(Integer studentId) {
try{
TimeUnit.SECONDS.sleep(10);
}catch