大批量推送项目日记(三):正确防止接口被短时间内多次调用的方法
2020.8.5
今天,本人发现了一个问题:
本人编写的代码提供了一个接口(url),当接口被调用时,会先从数据库中查找status不为1的记录(也就是未推送与推送失败的记录),获取每行的userID,然后把userID当做参数发送一个http请求,发送完毕后根据返回信息修改status,记为1(推送成功)或2(推送失败),以此实现了给用户推送信息。
正常情况下,调用一次本人的接口后,status会被修改,成功的改为1,失败的改为2;不影响下次调用。
但是,如果有人在短时间内多次调用本人的接口,会造成多个线程从数据库中查到相同的数据(此时status还没有来得及被修改),然后多个线程发送相同的http请求,就会造成一个用户收到多个相同的推送信息。
为了解决这个问题,本人想到了一个方法,代码如下(自测没有问题):
//记录当前线程的变量,不允许多个线程同时运行
public static Thread nowThread = null;
......
//线程主方法
public void pushTask(){
//如果有正在执行的线程,新线程就不继续执行
if(nowThread != null && nowThread.isAlive()){
LOG.info("当前存在正在执行的线程,本次线程不执行,请稍后再试");
return;
}
else{
nowThread = Thread.currentThread();
}
//主要代码省略
......
//线程执行完毕,置空
nowThread = null;
}
1.上方的代码增加了一个static类型的Thread对象,保存上一次执行过的线程对象
2.当一个新的线程执行到该方法时,进行判断,如果上一次执行的线程不为null且存活,则自己不再执行,直接return
3.否则,新线程把自己的对象保存到nowThread
4.线程执行完成时,将nowThread置为null(这个好像不写也可以)
5.即使线程执行到一半意外停止,也不会影响新线程的执行,新线程根据isAlive()方法可以判断出来上一个线程是否存活。
-----------------------------------------------------------------------------------------------------------------------------
这个方法目前自测没有发现问题,也许不是最好的解决方法,但是应该能解决问题了。
如果大家有更好的解决方法,欢迎在评论区留言,谢谢!