public void releaseConnection(NHttpClientConnection conn) {
   if (conn == null) {
     return;
   }
   if (this.shutdown) {
     return;
   }
   synchronized (this.lock) {
     if (this.allConns.contains(conn)) {
       if (conn.isOpen()) {
         conn.setSocketTimeout(0);
         AsyncConnectionRequest request = this.pendingRequests.poll();
         if (request != null) {
           System.out.println("Re-using persistent connection");
           request.setConnection(conn);
         } else {
           this.availableConns.add(conn);
         }
       } else {
         this.allConns.remove(conn);
         processRequests();
       }
     }
   }
 }
 public void shutdown(long waitMs) throws IOException {
   synchronized (this.lock) {
     if (!this.shutdown) {
       this.shutdown = true;
       while (!this.pendingRequests.isEmpty()) {
         AsyncConnectionRequest request = this.pendingRequests.remove();
         request.cancel();
       }
       this.availableConns.clear();
       this.allConns.clear();
     }
   }
   this.ioreactor.shutdown(waitMs);
 }
 public AsyncConnectionRequest requestConnection() {
   if (this.shutdown) {
     throw new IllegalStateException("Connection manager has been shut down");
   }
   AsyncConnectionRequest request = new AsyncConnectionRequest();
   synchronized (this.lock) {
     while (!this.availableConns.isEmpty()) {
       NHttpClientConnection conn = this.availableConns.remove();
       if (conn.isOpen()) {
         System.out.println("Re-using persistent connection");
         request.setConnection(conn);
         break;
       } else {
         this.allConns.remove(conn);
       }
     }
     if (!request.isCompleted()) {
       this.pendingRequests.add(request);
       processRequests();
     }
   }
   return request;
 }
  public static void main(String[] args) throws Exception {
    HttpParams params = new BasicHttpParams();
    params
        .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
        .setIntParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 10000)
        .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
        .setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
        .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY, true)
        .setParameter(CoreProtocolPNames.USER_AGENT, "HttpComponents/1.1");

    BasicHttpProcessor httpproc = new BasicHttpProcessor();
    httpproc.addInterceptor(new RequestContent());
    httpproc.addInterceptor(new RequestTargetHost());
    httpproc.addInterceptor(new RequestConnControl());
    httpproc.addInterceptor(new RequestUserAgent());
    httpproc.addInterceptor(new RequestExpectContinue());

    // Set up protocol handler
    BufferingHttpClientHandler protocolHandler =
        new BufferingHttpClientHandler(
            httpproc,
            new MyHttpRequestExecutionHandler(),
            new DefaultConnectionReuseStrategy(),
            params);
    protocolHandler.setEventListener(new EventLogger());

    // Limit the total maximum of concurrent connections to 5
    int maxTotalConnections = 5;

    // Use the connection manager to maintain a pool of connections to localhost:8080
    final AsyncConnectionManager connMgr =
        new AsyncConnectionManager(
            new HttpHost("localhost", 8080), maxTotalConnections, protocolHandler, params);

    // Start the I/O reactor in a separate thread
    Thread t =
        new Thread(
            new Runnable() {

              public void run() {
                try {
                  connMgr.execute(); // The connection manager wraps the I/O reactor.
                } catch (InterruptedIOException ex) {
                  System.err.println("Interrupted");
                } catch (IOException e) {
                  System.err.println("I/O error: " + e.getMessage());
                }
                System.out.println("I/O reactor terminated");
              }
            });
    t.start();

    // Submit 50 requests using maximum 5 concurrent connections
    Queue<RequestHandle> queue = new LinkedList<RequestHandle>();
    for (int i = 0; i < 50; i++) {
      AsyncConnectionRequest connRequest =
          connMgr.requestConnection(); // Get a working connection from the connection manager.
      connRequest
          .waitFor(); // Wait for the connection request to be completed to the target authority.
      NHttpClientConnection conn =
          connRequest.getConnection(); // Get the real connection from the connection request.
      if (conn == null) {
        System.err.println("Failed to obtain connection");
        break;
      }

      HttpContext context = conn.getContext();
      BasicHttpRequest httpget = new BasicHttpRequest("GET", "/", HttpVersion.HTTP_1_1);
      RequestHandle handle = new RequestHandle(connMgr, conn);

      context.setAttribute("request", httpget);
      context.setAttribute("request-handle", handle);

      queue.add(handle);
      conn.requestOutput();
    }

    // Wait until all requests have been completed
    while (!queue.isEmpty()) {
      RequestHandle handle = queue.remove();
      handle.waitFor();
    }

    // Give the I/O reactor 10 sec to shut down
    connMgr.shutdown(10000);
    System.out.println("Done");
  }
 public void connected(NHttpClientConnection conn, Object attachment) {
   AsyncConnectionRequest request = (AsyncConnectionRequest) attachment;
   this.handler.connected(conn, attachment);
   this.connMgr.addConnection(conn);
   request.setConnection(conn);
 }