title: AsyncHttpClient creates how much threads?
body: <p>I use async http client in my code to asynchronously handle GET responses
  I can run simultaneously 100 requests in the same time.</p>
  
  <p>I use just on instance of httpClient in container</p>
  
  <pre><code>@Bean(destroyMethod = "close")
  open fun httpClient() = Dsl.asyncHttpClient()
  </code></pre>
  
  <p>Code looks like</p>
  
  <pre><code>fun method(): CompletableFuture&lt;String&gt; {
      return httpClient.prepareGet("someUrl").execute()
          .toCompletableFuture()
          .thenApply(::getResponseBody)
  }
  </code></pre>
  
  <p>It works fine functionally. In my testing I use mock endpoint with the same url address. But my expectation was that all the requests are handled in several threads, but in profiler I can see that 16 threads are created for AsyncHttpClient, and they aren't destroyed, even if there are no requests to send.</p>
  
  <p><a href="https://i.stack.imgur.com/POrX1.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/POrX1.png" alt="profiler screenshoot"></a></p>
  
  <p>My expectation was that </p>
  
  <ul>
  <li>it will be less threads for async client</li>
  <li>threads will be destroyed after some configured timeout</li>
  <li>is there some option to control how much threads can be created by asyncHttpClient?</li>
  </ul>
  
  <p>Am I missing something in my expectations?</p>
  
  <p><strong>UPDATE 1</strong>
  I saw instruction on <a href="https://github.com/AsyncHttpClient/async-http-client/wiki/Connection-pooling" rel="nofollow noreferrer">https://github.com/AsyncHttpClient/async-http-client/wiki/Connection-pooling</a>
  I found no info on thread pool</p>
  
  <p><strong>UPDATE 2</strong>
  I also created method to do the same, but with handler and additional executor pool</p>
  
  <p>Utility method look like</p>
  
  <pre><code>fun &lt;Value, Result&gt; CompletableFuture&lt;Value&gt;.handleResultAsync(executor: Executor, initResultHandler: ResultHandler&lt;Value, Result&gt;.() -&gt; Unit): CompletableFuture&lt;Result&gt; {
      val rh = ResultHandler&lt;Value, Result&gt;()
      rh.initResultHandler()
  
      val handler = BiFunction { value: Value?, exception: Throwable? -&gt;
          if (exception == null) rh.success?.invoke(value) else rh.fail?.invoke(exception)
      }
  
      return handleAsync(handler, executor)
  }
  </code></pre>
  
  <p>The updated method look like</p>
  
  <pre><code>fun method(): CompletableFuture&lt;String&gt; {
      return httpClient.prepareGet("someUrl").execute()
          .toCompletableFuture()
          .handleResultAsync(executor) {
              success = {response -&gt;
                  logger.info("ok")
                  getResponseBody(response!!)
              }
              fail = { ex -&gt;
                  logger.error("Failed to execute request", ex)
                  throw ex
              }
      }
  }
  </code></pre>
  
  <p>Then I can see that result of GET method is executed in the threads provided by thread pool (previously result was executed in "AsyncHttpClient-3-x"), but additional thread for AsyncHttpClient are still created and not destroyed.</p>