Skip to content

Commit ce85c81

Browse files
committed
Do not create a thread pool in AsyncHttpClientConfig.
Developers may still specify a service that they may wish to share with the AHC instance. By having this not be configured by default, it will allow providers to provide more optimized configurations out of the box.
1 parent 322bca8 commit ce85c81

File tree

5 files changed

+69
-50
lines changed

5 files changed

+69
-50
lines changed

api/src/main/java/org/asynchttpclient/AsyncHttpClientConfig.java

Lines changed: 20 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ public class AsyncHttpClientConfig {
106106
protected boolean allowSslConnectionPool;
107107
protected boolean useRawUrl;
108108
protected boolean removeQueryParamOnRedirect;
109-
protected boolean managedApplicationThreadPool;
110109
protected HostnameVerifier hostnameVerifier;
111110
protected int ioThreadMultiplier;
112111
protected boolean strict302Handling;
@@ -157,8 +156,7 @@ private AsyncHttpClientConfig(int maxTotalConnections,
157156
int spdyInitialWindowSize,
158157
int spdyMaxConcurrentStreams,
159158
boolean rfc6265CookieEncoding,
160-
boolean asyncConnectMode,
161-
boolean managedApplicationThreadPool) {
159+
boolean asyncConnectMode) {
162160

163161
this.maxTotalConnections = maxTotalConnections;
164162
this.maxConnectionPerHost = maxConnectionPerHost;
@@ -190,7 +188,6 @@ private AsyncHttpClientConfig(int maxTotalConnections,
190188
this.ioThreadMultiplier = ioThreadMultiplier;
191189
this.strict302Handling = strict302Handling;
192190
this.useRelativeURIsWithSSLProxies = useRelativeURIsWithSSLProxies;
193-
this.managedApplicationThreadPool = managedApplicationThreadPool;
194191
this.applicationThreadPool = applicationThreadPool;
195192
this.proxyServerSelector = proxyServerSelector;
196193
this.useRawUrl = useRawUrl;
@@ -334,25 +331,13 @@ public boolean isCompressionEnabled() {
334331
* asynchronous response.
335332
*
336333
* @return the {@link java.util.concurrent.ExecutorService} an {@link AsyncHttpClient} use for handling
337-
* asynchronous response.
334+
* asynchronous response. If no {@link ExecutorService} has been explicitly provided,
335+
* this method will return <code>null</code>
338336
*/
339337
public ExecutorService executorService() {
340338
return applicationThreadPool;
341339
}
342340

343-
/**
344-
* @return <code>true</code> if this <code>AsyncHttpClientConfig</code> instance created the
345-
* {@link ExecutorService} returned by {@link #executorService()}, otherwise returns <code>false</code>.
346-
* The return from this method is typically used by the various provider implementations to determine
347-
* if it should shutdown the {@link ExecutorService} when the {@link AsyncHttpClient} is closed. Developers
348-
* should take care and not share managed {@link ExecutorService} instances between client instances.
349-
*
350-
* @since 2.2.0
351-
*/
352-
public boolean isManagedExecutorService() {
353-
return managedApplicationThreadPool;
354-
}
355-
356341
/**
357342
* An instance of {@link ProxyServer} used by an {@link AsyncHttpClient}
358343
*
@@ -631,7 +616,6 @@ public static class Builder {
631616
private boolean useRelativeURIsWithSSLProxies = Boolean.getBoolean(ASYNC_CLIENT + "useRelativeURIsWithSSLProxies");
632617
private ScheduledExecutorService reaper;
633618
private ExecutorService applicationThreadPool;
634-
private boolean managedApplicationThreadPool;
635619
private ProxyServerSelector proxyServerSelector = null;
636620
private SSLContext sslContext;
637621
private SSLEngineFactory sslEngineFactory;
@@ -1272,23 +1256,22 @@ public Thread newThread(Runnable r) {
12721256
});
12731257
}
12741258

1275-
if (applicationThreadPool == null) {
1276-
managedApplicationThreadPool = true;
1277-
applicationThreadPool =
1278-
Executors.newCachedThreadPool(new ThreadFactory() {
1279-
final AtomicInteger counter = new AtomicInteger();
1280-
public Thread newThread(Runnable r) {
1281-
Thread t = new Thread(r,
1282-
"AsyncHttpClient-Callback-" + counter.incrementAndGet());
1283-
t.setDaemon(true);
1284-
return t;
1285-
}
1286-
});
1287-
}
1288-
1289-
if (applicationThreadPool.isShutdown()) {
1290-
throw new IllegalStateException("ExecutorServices closed");
1291-
}
1259+
// if (applicationThreadPool == null) {
1260+
// applicationThreadPool =
1261+
// Executors.newCachedThreadPool(new ThreadFactory() {
1262+
// final AtomicInteger counter = new AtomicInteger();
1263+
// public Thread newThread(Runnable r) {
1264+
// Thread t = new Thread(r,
1265+
// "AsyncHttpClient-Callback-" + counter.incrementAndGet());
1266+
// t.setDaemon(true);
1267+
// return t;
1268+
// }
1269+
// });
1270+
// }
1271+
//
1272+
// if (applicationThreadPool.isShutdown()) {
1273+
// throw new IllegalStateException("ExecutorServices closed");
1274+
// }
12921275

12931276
if (proxyServerSelector == null && useProxySelector) {
12941277
proxyServerSelector = ProxyUtils.getJdkDefaultProxyServerSelector();
@@ -1339,8 +1322,7 @@ public Thread newThread(Runnable r) {
13391322
spdyInitialWindowSize,
13401323
spdyMaxConcurrentStreams,
13411324
rfc6265CookieEncoding,
1342-
asyncConnectMode,
1343-
managedApplicationThreadPool);
1325+
asyncConnectMode);
13441326
}
13451327
}
13461328
}

api/src/main/java/org/asynchttpclient/providers/jdk/JDKAsyncHttpProvider.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
import java.util.List;
7373
import java.util.Map;
7474
import java.util.concurrent.Callable;
75+
import java.util.concurrent.ExecutorService;
7576
import java.util.concurrent.TimeoutException;
7677
import java.util.concurrent.atomic.AtomicBoolean;
7778
import java.util.concurrent.atomic.AtomicInteger;
@@ -98,9 +99,18 @@ public class JDKAsyncHttpProvider implements AsyncHttpProvider {
9899

99100
private boolean bufferResponseInMemory = false;
100101

102+
private ExecutorService service;
103+
104+
private boolean managedExecutorService;
105+
101106
public JDKAsyncHttpProvider(AsyncHttpClientConfig config) {
102107

103108
this.config = config;
109+
service = config.executorService();
110+
managedExecutorService = (service == null);
111+
if (service == null) {
112+
service = AsyncHttpProviderUtils.createDefaultExecutorService();
113+
}
104114
AsyncHttpProviderConfig<?, ?> providerConfig = config.getAsyncHttpProviderConfig();
105115
if (providerConfig instanceof JDKAsyncHttpProviderConfig) {
106116
configure(JDKAsyncHttpProviderConfig.class.cast(providerConfig));
@@ -152,7 +162,7 @@ public <T> ListenableFuture<T> execute(Request request, AsyncHandler<T> handler,
152162
JDKFuture<T> f = (delegate == null) ? new JDKFuture<T>(handler, requestTimeout, urlConnection) : delegate;
153163
f.touch();
154164

155-
f.setInnerFuture(config.executorService().submit(new AsyncHttpUrlConnection<T>(urlConnection, request, handler, f)));
165+
f.setInnerFuture(service.submit(new AsyncHttpUrlConnection<T>(urlConnection, request, handler, f)));
156166
maxConnections.incrementAndGet();
157167

158168
return f;
@@ -193,6 +203,9 @@ private HttpURLConnection createUrlConnection(Request request) throws IOExceptio
193203

194204
public void close() {
195205
isClose.set(true);
206+
if (managedExecutorService) {
207+
service.shutdownNow();
208+
}
196209
}
197210

198211
public Response prepareResponse(HttpResponseStatus status, HttpResponseHeaders headers, List<HttpResponseBodyPart> bodyParts) {

api/src/main/java/org/asynchttpclient/util/AsyncHttpProviderUtils.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@
2828
import java.util.List;
2929
import java.util.Locale;
3030
import java.util.Vector;
31+
import java.util.concurrent.ExecutorService;
32+
import java.util.concurrent.Executors;
33+
import java.util.concurrent.ThreadFactory;
34+
import java.util.concurrent.atomic.AtomicInteger;
3135

3236
import org.asynchttpclient.AsyncHttpClientConfig;
3337
import org.asynchttpclient.AsyncHttpProvider;
@@ -582,4 +586,17 @@ public static String keepAliveHeaderValue(AsyncHttpClientConfig config) {
582586
public static int requestTimeout(AsyncHttpClientConfig config, Request request) {
583587
return request.getRequestTimeoutInMs() != 0 ? request.getRequestTimeoutInMs() : config.getRequestTimeoutInMs();
584588
}
589+
590+
public static ExecutorService createDefaultExecutorService() {
591+
return Executors.newCachedThreadPool(new ThreadFactory() {
592+
final AtomicInteger counter = new AtomicInteger();
593+
594+
public Thread newThread(Runnable r) {
595+
Thread t = new Thread(r,
596+
"AsyncHttpClient-Callback-" + counter.incrementAndGet());
597+
t.setDaemon(true);
598+
return t;
599+
}
600+
});
601+
}
585602
}

providers/grizzly/src/main/java/org/asynchttpclient/providers/grizzly/GrizzlyAsyncHttpProvider.java

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,13 +183,11 @@ public void close() {
183183
try {
184184
connectionManager.destroy();
185185
clientTransport.stop();
186-
if (clientConfig.isManagedExecutorService()) {
187-
final ExecutorService service = clientConfig.executorService();
188-
// service may be null due to a custom configuration that
189-
// leverages Grizzly's SameThreadIOStrategy.
190-
if (service != null) {
191-
service.shutdown();
192-
}
186+
final ExecutorService service = clientConfig.executorService();
187+
// service may be null due to a custom configuration that
188+
// leverages Grizzly's SameThreadIOStrategy.
189+
if (service != null) {
190+
service.shutdown();
193191
}
194192
if (timeoutExecutor != null) {
195193
timeoutExecutor.stop();

providers/netty/src/main/java/org/asynchttpclient/providers/netty/NettyAsyncHttpProvider.java

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,9 +132,11 @@
132132
import java.util.concurrent.Future;
133133
import java.util.concurrent.RejectedExecutionException;
134134
import java.util.concurrent.Semaphore;
135+
import java.util.concurrent.ThreadFactory;
135136
import java.util.concurrent.TimeUnit;
136137
import java.util.concurrent.TimeoutException;
137138
import java.util.concurrent.atomic.AtomicBoolean;
139+
import java.util.concurrent.atomic.AtomicInteger;
138140

139141
import static org.asynchttpclient.util.AsyncHttpProviderUtils.DEFAULT_CHARSET;
140142
import static org.asynchttpclient.util.DateUtil.millisTime;
@@ -183,6 +185,8 @@ public boolean remove(Object o) {
183185
private static SpnegoEngine spnegoEngine = null;
184186
private final Protocol httpProtocol = new HttpProtocol();
185187
private final Protocol webSocketProtocol = new WebSocketProtocol();
188+
private final boolean managedExecutorService;
189+
private ExecutorService service;
186190

187191
private static boolean isNTLM(List<String> auth) {
188192
return isNonEmpty(auth) && auth.get(0).startsWith("NTLM");
@@ -195,9 +199,14 @@ public NettyAsyncHttpProvider(AsyncHttpClientConfig config) {
195199
} else {
196200
asyncHttpProviderConfig = new NettyAsyncHttpProviderConfig();
197201
}
202+
service = config.executorService();
203+
managedExecutorService = (service == null);
204+
if (service == null) {
205+
service = AsyncHttpProviderUtils.createDefaultExecutorService();
206+
}
198207

199208
if (asyncHttpProviderConfig.isUseBlockingIO()) {
200-
socketChannelFactory = new OioClientSocketChannelFactory(config.executorService());
209+
socketChannelFactory = new OioClientSocketChannelFactory(service);
201210
this.allowReleaseSocketChannelFactory = true;
202211
} else {
203212
// check if external NioClientSocketChannelFactory is defined
@@ -214,7 +223,7 @@ public NettyAsyncHttpProvider(AsyncHttpClientConfig config) {
214223
}
215224
int numWorkers = config.getIoThreadMultiplier() * Runtime.getRuntime().availableProcessors();
216225
log.debug("Number of application's worker threads is {}", numWorkers);
217-
socketChannelFactory = new NioClientSocketChannelFactory(e, config.executorService(), numWorkers);
226+
socketChannelFactory = new NioClientSocketChannelFactory(e, service, numWorkers);
218227
this.allowReleaseSocketChannelFactory = true;
219228
}
220229
}
@@ -830,8 +839,8 @@ public void close() {
830839
}
831840
}
832841

833-
if (config.isManagedExecutorService()) {
834-
config.executorService().shutdown();
842+
if (managedExecutorService) {
843+
service.shutdown();
835844
}
836845
config.reaper().shutdown();
837846
if (this.allowReleaseSocketChannelFactory) {

0 commit comments

Comments
 (0)