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