大批量推送项目日记(三):正确防止接口被短时间内多次调用的方法

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()方法可以判断出来上一个线程是否存活。

-----------------------------------------------------------------------------------------------------------------------------

这个方法目前自测没有发现问题,也许不是最好的解决方法,但是应该能解决问题了。

如果大家有更好的解决方法,欢迎在评论区留言,谢谢!

原文地址:https://www.cnblogs.com/codeToSuccess/p/13906221.html