1
1
/*
2
- * Copyright 2002-2023 the original author or authors.
2
+ * Copyright 2002-2024 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
19
19
import java .io .IOException ;
20
20
import java .io .ObjectInputStream ;
21
21
import java .io .Serializable ;
22
+ import java .util .concurrent .locks .Condition ;
23
+ import java .util .concurrent .locks .Lock ;
24
+ import java .util .concurrent .locks .ReentrantLock ;
22
25
23
26
import org .apache .commons .logging .Log ;
24
27
import org .apache .commons .logging .LogFactory ;
@@ -60,7 +63,9 @@ public abstract class ConcurrencyThrottleSupport implements Serializable {
60
63
/** Transient to optimize serialization. */
61
64
protected transient Log logger = LogFactory .getLog (getClass ());
62
65
63
- private transient Object monitor = new Object ();
66
+ private final Lock concurrencyLock = new ReentrantLock ();
67
+
68
+ private final Condition concurrencyCondition = this .concurrencyLock .newCondition ();
64
69
65
70
private int concurrencyLimit = UNBOUNDED_CONCURRENCY ;
66
71
@@ -109,7 +114,8 @@ protected void beforeAccess() {
109
114
}
110
115
if (this .concurrencyLimit > 0 ) {
111
116
boolean debug = logger .isDebugEnabled ();
112
- synchronized (this .monitor ) {
117
+ this .concurrencyLock .lock ();
118
+ try {
113
119
boolean interrupted = false ;
114
120
while (this .concurrencyCount >= this .concurrencyLimit ) {
115
121
if (interrupted ) {
@@ -121,7 +127,7 @@ protected void beforeAccess() {
121
127
" has reached limit " + this .concurrencyLimit + " - blocking" );
122
128
}
123
129
try {
124
- this .monitor . wait ();
130
+ this .concurrencyCondition . await ();
125
131
}
126
132
catch (InterruptedException ex ) {
127
133
// Re-interrupt current thread, to allow other threads to react.
@@ -134,6 +140,9 @@ protected void beforeAccess() {
134
140
}
135
141
this .concurrencyCount ++;
136
142
}
143
+ finally {
144
+ this .concurrencyLock .unlock ();
145
+ }
137
146
}
138
147
}
139
148
@@ -144,12 +153,16 @@ protected void beforeAccess() {
144
153
protected void afterAccess () {
145
154
if (this .concurrencyLimit >= 0 ) {
146
155
boolean debug = logger .isDebugEnabled ();
147
- synchronized (this .monitor ) {
156
+ this .concurrencyLock .lock ();
157
+ try {
148
158
this .concurrencyCount --;
149
159
if (debug ) {
150
160
logger .debug ("Returning from throttle at concurrency count " + this .concurrencyCount );
151
161
}
152
- this .monitor .notify ();
162
+ this .concurrencyCondition .signal ();
163
+ }
164
+ finally {
165
+ this .concurrencyLock .unlock ();
153
166
}
154
167
}
155
168
}
@@ -165,7 +178,6 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFound
165
178
166
179
// Initialize transient fields.
167
180
this .logger = LogFactory .getLog (getClass ());
168
- this .monitor = new Object ();
169
181
}
170
182
171
183
}
0 commit comments