title: Concurrent requests via Apache Http Client (and java.util.concurrent) seem to finish correctly but crash my OS
body: <p>i am currently learning to use the the concurrent features of Java provided by the package java.util.concurrent. As an exercise i tried to write a little program that could be used to performance test a HTTP API. But somehow my program is not terminating correctly very often. It even crashes my OS.</p>
  
  <p>Following is the <strong>pseudo code of my program</strong>:</p>
  
  <ul>
  <li>Instantiate Request Objects, that query an HTTP API (In the example i just query one random site). </li>
  <li>Instantiate multiple Callables, where each one represents a represents an Http Call.</li>
  <li>Iterate over the Callables and schedule them via a ScheduledExecutorService (how many requests should be performed per second can be configured at the begin of the code).</li>
  <li>After scheduling all Callables, i am beginning to iterate over the Futures. If a futures is done, retrieve the response. Do this every second. If no new Future was finished, quit the loop.</li>
  </ul>
  
  <p><strong>What problems am i experiencing in detail?</strong></p>
  
  <ul>
  <li>Lots of times, the program is not finishing correctly. I see all log prints in the console, as if the program is finishing correctly. But actually i am seeing that stop button in eclipse still remains active <img src="https://dl.dropbox.com/u/4345970/Bildschirmfoto%202012-12-08%20um%2014.58.57.png" alt="stop">. If i click it, it says that the program could not be terminated correctly. It does not finish no matter how i long i wait (NOTE: I am starting the program inside eclipse).</li>
  <li>I can provoke the error easily if i am increasing the number of Requests. If am turning up to 2000, this will happen for sure. If it happens my OS even crashes, i can still use eclipse, but other apps do not work anymore.</li>
  <li>My Environment is Eclipse 3.7 on Mac OS X 10.7 with Java 1.6 and Apache httpclient 4.2.2</li>
  </ul>
  
  <p>Do you spot any major erros in my code? Before i have never had such issues in a java program with crashing my OS and seeing no exceptions at all.</p>
  
  <p><strong>The code:</strong></p>
  
  <pre><code>public class ConcurrentHttpRequestsTest {
  
      /**
       * @param args
       */
      public static void main(String[] args) {
          ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(25);
  
          Integer standardTimeout = 5000;
          Float numberOfRequestsPerSecond = 50.0f;
          Integer numberOfRequests = 500;
          Integer durationBetweenRequests = Math.round(1000 / numberOfRequestsPerSecond);
  
          // build Http Request
          HttpGet request = null;
          request = new HttpGet("http://www.spiegel.de");
          // request.addHeader("Accept", "application/json");
          HttpParams params = new BasicHttpParams();
          HttpConnectionParams.setConnectionTimeout(params, standardTimeout);
          HttpConnectionParams.setSoTimeout(params, standardTimeout);
          request.setParams(params);
  
          // setup concurrency logic
          Collection&lt;Callable&lt;Long&gt;&gt; callables = new LinkedList&lt;Callable&lt;Long&gt;&gt;();
          for (int i = 1; i &lt;= numberOfRequests; i++) {
              HttpClient client = new DefaultHttpClient();
              callables.add(new UriCallable(request, client));
          }
  
          // start performing requests
          int i = 1;
          Collection&lt;Future&lt;Long&gt;&gt; futures = new LinkedList&lt;Future&lt;Long&gt;&gt;();
          for (Callable&lt;Long&gt; callable : callables) {
              ScheduledFuture&lt;Long&gt; future = scheduledExecutorService.schedule(callable, i * durationBetweenRequests, TimeUnit.MILLISECONDS);
              futures.add(future);
              i++;
          }
  
          // process futures (check wether they are ready yet)
          Integer maximumNoChangeCount = 5;
          boolean futuresAreReady = false;
          int noChangeCount = 0;
          int errorCount = 0;
          List&lt;Long&gt; responses = new LinkedList&lt;Long&gt;();
          while (!futuresAreReady) {
              boolean allFuturesAreDone = true;
              boolean atLeast1FutureIsDone = false;
              Iterator&lt;Future&lt;Long&gt;&gt; iterator = futures.iterator();
  
              while (iterator.hasNext()) {
                  Future&lt;Long&gt; future = iterator.next();
                  allFuturesAreDone = allFuturesAreDone &amp;&amp; (future.isDone());
                  if (future.isDone()) {
                      try {
                          atLeast1FutureIsDone = true;
                          responses.add(future.get());
                          iterator.remove();
                      } catch (Exception e) {
                          // remove failed futures (e.g. timeout)
                          // System.out.println("Reached catch of future.get()" +
                          // e.getClass() + " " + e.getCause().getClass() + " " +
                          // e.getMessage());
  
                          iterator.remove();
                          errorCount++;
                      }
                  }
                  if (future.isCancelled()) {
                      // this code is never reached. Just here to make sure that
                      // this is not the cause of problems.
                      System.out.println("Found a cancelled future. Will remove it.");
                      iterator.remove();
                  }
              }
              if (!atLeast1FutureIsDone) {
                  System.out.println("At least 1 future was not done. Current noChangeCount:" + noChangeCount);
                  noChangeCount++;
              } else {
                  // reset noChangeCount
                  noChangeCount = 0;
              }
              futuresAreReady = allFuturesAreDone;
  
              // log the current state of responses, errors and remaining futures
              System.out.println("Size of responses :" + responses.size() + "; Size of futures:" + futures.size() + " Errors:" + errorCount);
              if (noChangeCount &gt;= maximumNoChangeCount) {
                  System.out.println("Breaking while loop becauce no new future finished in the last " + maximumNoChangeCount + " iterations");
                  break;
              }
              // check every second
              try {
                  Thread.sleep(1000);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
          }
  
          for (Long responsetime : responses) {
              // analyze responsetimes or whatever
          }
          // clean up
          // .shutdown() made even more problems than shutdownNow()
          scheduledExecutorService.shutdownNow();
          System.out.println("Executors have been shutdown - Main Method finished. Will exit System.");
          System.out.flush();
          System.exit(0);
      }
  
      private static class UriCallable implements Callable&lt;Long&gt; {
          private HttpUriRequest request;
          private HttpClient client;
  
          public UriCallable(HttpUriRequest request, HttpClient client) {
              super();
              this.request = request;
              this.client = client;
          }
  
          public Long call() throws Exception {
              Long start = System.currentTimeMillis();
              HttpResponse httpResponse = client.execute(request);
              Long end = System.currentTimeMillis();
              return end - start;
          }
      }
  
  }
  </code></pre>