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

    } 


} 

이 코드를 실행하는 동안, 나는 다음과 같은 예외가 얻을 : 내가 HTTP 요청을 실행하면멀티 스레딩 세션 객체

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 

, 그때 나는이 예외를 참조하십시오. 그것은 단일 스레드에 대해 완벽하게 작동합니다. 내가 완벽하게 잘 작동하는 특정 URL을 호출하려고하지만 그것에 하나 이상의 스레드를 추가 할 때, 그것은 잘못된 상태 예외를 throw합니다.

+1

스택 트레이스 읽기를 배우십시오. – mre

답변

3

볼 수 있습니다! httpClient와 httpRequest는 모두 정적이었습니다. 내가 정적이 아닌 그들을 만든 후 잘 작동합니다! Executor Service는 쓰레드 관리에 대한 더 나은 제어권을 제공합니다.

7

멀티 스레드 HttpConnectionManager를 정의해야합니다. 예 :

자세한 내용은
MultiThreadedHttpConnectionManager connectionManager = 
            new MultiThreadedHttpConnectionManager(); 
HttpClient client = new HttpClient(connectionManager); 

내가 나의 어리 석음을 깨달았다 http://hc.apache.org/httpclient-3.x/threading.html

7

여기에 MultiThreadedHttpConnectionManager가 구식입니다. - (HttpClient를 버전> = 4.3로) 연결 관리자가 다시 한번 갱신하고 있으며, 지금은 PoolingHttpClientConnectionManager를 사용한다 또한 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 *)이 길이다 대신. PoolingHttpClientConnectionManager의 기본 제한 사항은 총 20 개의 연결이며 경로 당 2 개입니다. 그러나이를 오버라이드 할 수 있습니다.

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