Semaphore信号量限制单一接口流量

编程

最近碰到一个需求,有一个导入操作,期望是一次只有一个请求在进行导入,不允许多个线程同时执行这个操作,首先考虑的是用熔断器来做的,熔断器里面y有一个线程的限制,但后面发现总有些奇怪的bug,放弃。然后打算用redis来做分布式全局锁,可这个项目没有引入redis,也感觉没必要引入,放弃,然后发现了Semaphore信号量这个类,感觉用这个可以解决问题。

看代码

@RestController

@RequestMapping("/dr")

public class TestController {

    //这里你要限制一次请求多少,就写多少。

    private static Semaphore semaphore = new Semaphore(1);

    @PostMapping("/import")

     @ResponseBody

    public ResultJson executeImport(@RequestParam("examFile") MultipartFile examFile){

        boolean permit = false;

        try {    

            permit = semaphore.tryAcquire();

            if (!permit){

            log.info("获取信号量失败");

            return new ResultJson("已有导入任务执行中,请稍后重试!");

            }

            //你的导入操作

        } finally{           

            //不能随便释放许可,每次释放都会让信号量+1,导致异常!

            if (permit){

             semaphore.release();

            }

        }

    }

}

上面的代码要注意几点,网上抄的其他代码都存在一些坑。

第一,如果你的代码不需要阻塞,直接使用 tryAcquire() 获取比较好,网上很多代码直接先判断剩余的许可数量,然后再走获取,但实际上,这种操作在并发环境下并不安全,会导致大量的阻塞,阻塞后会按照你设定的规则,公平锁形式或非公平形式的等待许可,如果不需要阻塞,直接换 tryAcquire()即可。

第二,释放许可必须放到finally中,如果代码中断异常,就丢失了一个许可。第二,需要必须要判断一下,当前是不是获得了许可,你看源码的话就发现,释放一次,许可+1,这意味着,如果你没有获取许可,也会+1,你初始化的 Semaphore semaphore = new Semaphore(1); 也被改变了!

以上是 Semaphore信号量限制单一接口流量 的全部内容, 来源链接: utcz.com/z/517214.html

回到顶部