2011-11-15 67 views
7
public class test { 
    public static final int nThreads = 2; 

    public static void main(String[] args) throws ExecutionException, InterruptedException{ 
    // Runnable myrunnable = new myRunnable(); 
     ExecutorService execute = Executors.newFixedThreadPool(nThreads); 

     for (int i = 0; i < nThreads; ++i) { 
      execute.execute(new MyTask()); 
     }   

     execute.awaitTermination(1000, TimeUnit.MILLISECONDS); 

     execute.shutdown(); 
    } 
} 

class MyTask implements Runnable { 
    public static final int maxCalls = 10; 
    public static final int sleepMillis = 500; 
    private static HttpResponse response; 
    private static HttpClient httpclient; 

    public void run(){ 
     int counter = 0; 

     while (true) { 

      if (counter >= maxCalls) { 
       break; 
      } 
      try { 
       Thread.currentThread().sleep(sleepMillis); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

      execHttpRequest(); 

      ++counter; 
     } 
    } 

    private void execHttpRequest() { 
     httpclient = new DefaultHttpClient(); 
     HttpGet httpget = new HttpGet("My URL"); 

     try { 

      response = httpclient.execute(httpget); 
      BufferedReader br = new BufferedReader(new InputStreamReader(response.getEntity().getContent())); 
      String output; 
      while((output=br.readLine())!=null){ 
       System.out.println(Thread.currentThread().getName() +output); 
      } 
      br.close(); 

      httpclient.getConnectionManager().shutdown(); 
      //httpclient.getConnectionManager().shutdown(); 
     } catch (ClientProtocolException e) { 
      e.printStackTrace(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
     } 
     finally{ 

      httpclient.getConnectionManager().shutdown(); 
     } 

    } 


} 

虽然运行此代码,我得到以下异常:多线程的HttpClient

Exception in thread "pool-1-thread-1" java.lang.IllegalStateException: Invalid use of SingleClientConnManager: connection still allocated. 
Make sure to release the connection before allocating another one. 
    at org.apache.http.impl.conn.SingleClientConnManager.getConnection(SingleClientConnManager.java:216) 
    at org.apache.http.impl.conn.SingleClientConnManager$1.getConnection(SingleClientConnManager.java:190) 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:401) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732) 
    at MyTask.execHttpRequest(test.java:72) 
    at MyTask.run(test.java:60) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) 
    at java.lang.Thread.run(Thread.java:722) 
java.io.InterruptedIOException: Connection has been shut down 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:543) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754) 
    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732) 
    at MyTask.execHttpRequest(test.java:72) 
    at MyTask.run(test.java:60) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) 
    at java.lang.Thread.run(Thread.java:722) 
Caused by: org.apache.http.impl.conn.ConnectionShutdownException 
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.assertValid(AbstractPooledConnAdapter.java:86) 
    at org.apache.http.impl.conn.AbstractPooledConnAdapter.getRoute(AbstractPooledConnAdapter.java:112) 
    at org.apache.http.impl.client.DefaultRequestDirector.establishRoute(DefaultRequestDirector.java:740) 
    at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:577) 
    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:425) 
    ... 8 more 

当我执行HTTP请求,然后我看到这些例外。它对于单线程来说工作得很好。我试图调用一个特定的URL(它工作得很好),但是当我向它添加多个线程时,它会抛出一个非法的状态异常。

+1

学习阅读堆栈跟踪。 – mre

回答

3

我意识到自己的愚蠢! httpClient和httpRequest都是静态的。我让他们非静态后,它工作正常!执行器服务使我能够更好地控制线程管理,并且非常乐意使用它。

7

您需要定义多线程HttpConnectionManager例如

MultiThreadedHttpConnectionManager connectionManager = 
            new MultiThreadedHttpConnectionManager(); 
HttpClient client = new HttpClient(connectionManager); 

有关详细信息,你可以看到http://hc.apache.org/httpclient-3.x/threading.html

7

来到这里来说,MultiThreadedHttpConnectionManager已经过时了。目前(HttpClient的版本4 *)这是这样的:http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e639

SchemeRegistry schemeRegistry = new SchemeRegistry(); 
schemeRegistry.register(
     new Scheme("http", 80, PlainSocketFactory.getSocketFactory())); 

ClientConnectionManager cm = new PoolingClientConnectionManager(schemeRegistry); 
HttpClient httpClient = new DefaultHttpClient(cm); 
1

除了bpgergo答案是 - 连接管理器再次更新(由于HttpClient的版本> = 4.3),现在你应该使用PoolingHttpClientConnectionManager代替。 PoolingHttpClientConnectionManager的默认限制总共有20个连接,每个路由2个 - 但这些可以被覆盖。

PoolingHttpClientConnectionManager cm=new PoolingHttpClientConnectionManager(); 
cm.setDefaultMaxPerRoute(40); 
cm.setMaxTotal(500); 
CloseableHttpClient client = HttpClients.createMinimal(cm);