Semaphore原意是指信號(hào)量,從API的注釋:"Semaphores are often used to restrict the number of threads than can access some (physical or logical) resource"可以看出,Semaphore一般是用來(lái)限制線程能夠使用的資源個(gè)數(shù).
應(yīng)用場(chǎng)景
在Web開(kāi)發(fā)中,Semaphore可以用來(lái)限制某個(gè)接口的并發(fā)調(diào)用次數(shù).可以在Sping的Context中維護(hù)一個(gè)Map,key可以是處理線程,value可以是一個(gè)Semaphore對(duì)象.通過(guò)這樣的方式,就可以實(shí)現(xiàn)系統(tǒng)同時(shí)處理的線程數(shù)不會(huì)超過(guò)某個(gè)閾值.
代碼實(shí)現(xiàn)
我們可以通過(guò)WebFilter注解,來(lái)實(shí)現(xiàn)一個(gè)過(guò)濾器,在過(guò)濾器中攔截所有的請(qǐng)求調(diào)用,然后通過(guò)Semaphore來(lái)進(jìn)行計(jì)數(shù),如果超過(guò)總的計(jì)數(shù),則返回相應(yīng)的提示信息.當(dāng)然也可以對(duì)URL進(jìn)行細(xì)化,針對(duì)每個(gè)API提供對(duì)應(yīng)的限制.
/**
* API并發(fā)控制過(guò)濾器
* Created by qiaohe
* Date: 19-7-1 上午11:54
*/
@Component
@WebFilter(urlPatterns = "/*", filterName = "concurrentRestrictFilter")
public class ConcurrentRestrictFilter implements Filter {
private Log log = LogFactory.getLog(getClass());
private static final Integer MAX_CONCURRENT_NUM = 1;
private static final Semaphore semaphore = new Semaphore(MAX_CONCURRENT_NUM);
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
log.info("before acquire: " + semaphore.availablePermits());
if(!semaphore.tryAcquire()){
if(response instanceof HttpServletResponse){
HttpServletResponse res = (HttpServletResponse)response;
res.setContentType(MimeTypeUtils.APPLICATION_JSON_VALUE);
res.sendError(HttpStatus.BAD_REQUEST.value(), "reach max current num");
}
return;
}
log.info("after acquire: " + semaphore.availablePermits());
try{
chain.doFilter(request, response);
} finally {
semaphore.release();
log.info("release: " + semaphore.availablePermits());
}
}
@Override
public void destroy() {
}
}
轉(zhuǎn)自: http://heqiao2010.github.io