1. /*
  2. * Copyright 2002-2004 the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.springframework.aop.interceptor;
  17. import org.aopalliance.intercept.MethodInterceptor;
  18. import org.aopalliance.intercept.MethodInvocation;
  19. import org.apache.commons.logging.Log;
  20. import org.apache.commons.logging.LogFactory;
  21. /**
  22. * Interceptor that throttles concurrent access, blocking invocations
  23. * if a specified concurrency limit is reached.
  24. *
  25. * <p>Can be applied to methods of local services that involve heavy use
  26. * of system resources, in a scenario where it is more efficient to
  27. * throttle concurrency for a specific service rather than restricting
  28. * the entire thread pool (e.g. the web container's thread pool).
  29. *
  30. * @author Juergen Hoeller
  31. * @since 11.02.2004
  32. */
  33. public class ConcurrencyThrottleInterceptor implements MethodInterceptor {
  34. protected final Log logger = LogFactory.getLog(getClass());
  35. private int concurrencyLimit = 1;
  36. private int concurrencyCount = 0;
  37. /**
  38. * Set the maximum number of parallel invocations that this interceptor
  39. * allows. Default is 1 (having the same effect as a synchronized block).
  40. */
  41. public void setConcurrencyLimit(int concurrencyLimit) {
  42. this.concurrencyLimit = concurrencyLimit;
  43. }
  44. public Object invoke(MethodInvocation methodInvocation) throws Throwable {
  45. boolean debug = logger.isDebugEnabled();
  46. synchronized (this) {
  47. while (this.concurrencyCount >= this.concurrencyLimit) {
  48. if (debug) {
  49. logger.debug("Concurrency count " + this.concurrencyCount +
  50. " has reached limit " + this.concurrencyLimit + " - blocking");
  51. }
  52. try {
  53. wait();
  54. }
  55. catch (InterruptedException ex) {
  56. }
  57. }
  58. if (debug) {
  59. logger.debug("Entering method at concurrency count " + this.concurrencyCount);
  60. }
  61. this.concurrencyCount++;
  62. }
  63. try {
  64. return methodInvocation.proceed();
  65. }
  66. finally {
  67. synchronized (this) {
  68. this.concurrencyCount--;
  69. if (debug) {
  70. logger.debug("Returning from method at concurrency count " + this.concurrencyCount);
  71. }
  72. notify();
  73. }
  74. }
  75. }
  76. }