25
25
import java .util .concurrent .ThreadFactory ;
26
26
import java .util .concurrent .atomic .AtomicBoolean ;
27
27
import java .util .concurrent .atomic .AtomicInteger ;
28
+ import java .util .concurrent .locks .Lock ;
29
+ import java .util .concurrent .locks .ReentrantLock ;
28
30
import java .util .function .Supplier ;
29
31
import java .util .stream .IntStream ;
30
32
import org .slf4j .Logger ;
@@ -42,12 +44,13 @@ class DefaultExecutorServiceFactory implements ExecutorServiceFactory {
42
44
private final int minSize ;
43
45
private final int clientPerExecutor ;
44
46
private final Supplier <Executor > executorFactory ;
47
+ private final Lock lock = new ReentrantLock ();
45
48
46
49
DefaultExecutorServiceFactory (int minSize , int clientPerExecutor , String prefix ) {
47
50
this .minSize = minSize ;
48
51
this .clientPerExecutor = clientPerExecutor ;
49
52
this .threadFactory = threadFactory (prefix );
50
- this .executorFactory = () -> newExecutor () ;
53
+ this .executorFactory = this :: newExecutor ;
51
54
List <Executor > l = new ArrayList <>(this .minSize );
52
55
IntStream .range (0 , this .minSize ).forEach (ignored -> l .add (this .executorFactory .get ()));
53
56
executors = new CopyOnWriteArrayList <>(l );
@@ -111,29 +114,39 @@ private Executor newExecutor() {
111
114
}
112
115
113
116
@ Override
114
- public synchronized ExecutorService get () {
115
- if (closed .get ()) {
116
- throw new IllegalStateException ("Executor service factory is closed" );
117
- } else {
118
- maybeResize (this .executors , this .minSize , this .clientPerExecutor , this .executorFactory );
119
- LOGGER .debug ("Looking least used executor in {}" , this .executors );
120
- Executor executor = this .executors .stream ().min (EXECUTOR_COMPARATOR ).get ();
121
- LOGGER .debug ("Least used executor is {}" , executor );
122
- executor .incrementUsage ();
123
- return executor .executorService ;
117
+ public ExecutorService get () {
118
+ this .lock .lock ();
119
+ try {
120
+ if (closed .get ()) {
121
+ throw new IllegalStateException ("Executor service factory is closed" );
122
+ } else {
123
+ maybeResize (this .executors , this .minSize , this .clientPerExecutor , this .executorFactory );
124
+ LOGGER .debug ("Looking least used executor in {}" , this .executors );
125
+ Executor executor = this .executors .stream ().min (EXECUTOR_COMPARATOR ).get ();
126
+ LOGGER .debug ("Least used executor is {}" , executor );
127
+ executor .incrementUsage ();
128
+ return executor .executorService ;
129
+ }
130
+ } finally {
131
+ this .lock .unlock ();
124
132
}
125
133
}
126
134
127
135
@ Override
128
- public synchronized void clientClosed (ExecutorService executorService ) {
129
- if (!closed .get ()) {
130
- Executor executor = find (executorService );
131
- if (executor == null ) {
132
- LOGGER .info ("Could not find executor service wrapper" );
133
- } else {
134
- executor .decrementUsage ();
135
- maybeResize (this .executors , this .minSize , this .clientPerExecutor , this .executorFactory );
136
+ public void clientClosed (ExecutorService executorService ) {
137
+ this .lock .lock ();
138
+ try {
139
+ if (!closed .get ()) {
140
+ Executor executor = find (executorService );
141
+ if (executor == null ) {
142
+ LOGGER .info ("Could not find executor service wrapper" );
143
+ } else {
144
+ executor .decrementUsage ();
145
+ maybeResize (this .executors , this .minSize , this .clientPerExecutor , this .executorFactory );
146
+ }
136
147
}
148
+ } finally {
149
+ this .lock .unlock ();
137
150
}
138
151
}
139
152
@@ -148,17 +161,26 @@ private Executor find(ExecutorService executorService) {
148
161
149
162
@ Override
150
163
public synchronized void close () {
151
- if (closed .compareAndSet (false , true )) {
152
- this .executors .forEach (executor -> executor .executorService .shutdownNow ());
164
+ this .lock .lock ();
165
+ try {
166
+ if (closed .compareAndSet (false , true )) {
167
+ this .executors .forEach (executor -> executor .executorService .shutdownNow ());
168
+ }
169
+ } finally {
170
+ this .lock .unlock ();
153
171
}
154
172
}
155
173
156
174
static class Executor {
157
175
176
+ private static final AtomicInteger ID_SEQUENCE = new AtomicInteger ();
177
+
158
178
private final ExecutorService executorService ;
159
179
private AtomicInteger usage = new AtomicInteger (0 );
180
+ private final int id ;
160
181
161
182
Executor (ExecutorService executorService ) {
183
+ this .id = ID_SEQUENCE .getAndIncrement ();
162
184
this .executorService = executorService ;
163
185
}
164
186
@@ -192,7 +214,7 @@ private void close() {
192
214
193
215
@ Override
194
216
public String toString () {
195
- return "Executor{" + "usage=" + usage .get () + '}' ;
217
+ return "Executor{" + "id=" + id + ", usage=" + usage .get () + '}' ;
196
218
}
197
219
}
198
220
}
0 commit comments