2011-11-15 24 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(); 
     } 

    } 


} 

Trong khi chạy mã này, tôi nhận được ngoại lệ sau đây:Multi-Threading 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 

Khi tôi thực hiện yêu cầu http, sau đó tôi nhìn thấy những trường hợp ngoại lệ. Nó hoạt động hoàn toàn tốt cho đơn luồng. Tôi đang cố gắng gọi một URL cụ thể (mà hoạt động hoàn toàn tốt đẹp) nhưng khi tôi thêm nhiều hơn một thread vào nó, nó ném một ngoại lệ bất hợp pháp nhà nước.

+1

Tìm hiểu cách đọc stacktraces. – mre

Trả lời

3

tôi nhận ra sự điên rồ của tôi! httpClient và httpRequest đều là tĩnh. Sau khi tôi làm cho họ không tĩnh nó hoạt động tốt! Executor Service cho phép tôi kiểm soát tốt hơn việc quản lý các luồng và tôi rất muốn sử dụng nó.

7

Bạn cần xác định HttpConnectionManager đa luồng, ví dụ:

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

Để biết thêm chi tiết bạn có thể thấy http://hc.apache.org/httpclient-3.x/threading.html

7

Đến đây để nói, MultiThreadedHttpConnectionManager đã lỗi thời. Hiện nay (HttpClient phiên bản 4. *) đây là cách: 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

Ngoài bpgergo câu trả lời của - người quản lý kết nối đã được cập nhật một lần nữa (như của HttpClient phiên bản> = 4.3), và bây giờ bạn nên sử dụng PoolingHttpClientConnectionManager thay thế. Các giới hạn mặc định của PoolingHttpClientConnectionManager là tổng cộng 20 kết nối và 2 kết nối cho mỗi tuyến - nhưng chúng có thể bị ghi đè.

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