Java tutorial
/* * Copyright (c) 2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.zkybase.kite.guard; import java.util.concurrent.Semaphore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.jmx.export.annotation.ManagedAttribute; import org.springframework.jmx.export.annotation.ManagedResource; import org.zkybase.kite.AbstractGuard; import org.zkybase.kite.GuardCallback; import org.zkybase.kite.exception.ConcurrencyLimitExceededException; /** * <p> * Guard that fails with an exception when a concurrency threshold is exceeded. * </p> * <p> * Implementation is based on a counting semaphore. * </p> * <p> * We expose this guard as a JMX MBean so it can be queried and manipulated in management contexts. * </p> * * @author Willie Wheeler (willie.wheeler@gmail.com) * @since 1.0 */ @ManagedResource public class ConcurrencyThrottleTemplate extends AbstractGuard { private static Logger log = LoggerFactory.getLogger(ConcurrencyThrottleTemplate.class); private final int limit; private final Semaphore semaphore; /** * Creates a concurrency throttle with the given limit. The throttle rejects requests in excess of the limit. * * @param limit concurrency limit * @throws IllegalArgumentException if limit < 1 */ public ConcurrencyThrottleTemplate(int limit) { if (limit < 1) { throw new IllegalArgumentException("limit must be >= 1"); } this.limit = limit; this.semaphore = new Semaphore(limit, true); } @ManagedAttribute(description = "Concurrency limit, after which requests are rejected") public int getLimit() { return limit; } public <T> T execute(GuardCallback<T> action) throws Exception { if (semaphore.tryAcquire()) { try { return action.doInGuard(); } finally { semaphore.release(); } } else { log.warn("Request rejected: concurrency limit {} exceeded", limit); throw new ConcurrencyLimitExceededException(limit); } } }