3楼的说法比较有道理。虽然未必是资源竞争等待,但缺省的HttpClient确实不支持并发,这意味很多成员变量在并发使用过程中会互相影响。如果非要用想某些Cookie信息之类的而不能每个线程独立使用一个HttpClient,建议考虑用 ThreadSafeClientConnManager协助管理,释放方式不复杂,网上也有不少例子。ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(); cm.setMaxTotal(50); HttpClient httpclient = new DefaultHttpClient(cm);
LZ 用我这个 HTTPCLIENT 池试试 package com.kanesoft.method.httppost;import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors;import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpPost; import org.apache.http.conn.scheme.PlainSocketFactory; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.protocol.HTTP;public class MultiThreadedHttpConnection { private static HttpClient httpClient; private static final String contextType = "text/xml;charset=UTF-8"; private static ExecutorService es = Executors.newFixedThreadPool(10); private static MultiThreadedHttpConnection mthc = new MultiThreadedHttpConnection(); private static String url = "http://localhost:8000/2.php"; private static int maxTotal = 300; private static int maxPerRout = 200; private static int connecttimeOut = 10000; private static int readTimeOut = 5000; static { ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(); cm.setMaxTotal(maxTotal); cm.setDefaultMaxPerRoute(maxPerRout); HttpParams params = new BasicHttpParams(); HttpConnectionParams.setConnectionTimeout(params, connecttimeOut); HttpConnectionParams.setSoTimeout(params, readTimeOut); httpClient = new DefaultHttpClient(cm, params); } private MultiThreadedHttpConnection() { } public static MultiThreadedHttpConnection getInstance() { return mthc; } public void httpAsyncSendByMap(final Map<String, String> map) { es.execute(new postThread(mthc, map)); } private int sendDataByPost(Map<String, String> map) { Integer statusCode = -1; HttpPost post = new HttpPost(url); List<NameValuePair> nvps = new ArrayList<NameValuePair>(); for (Map.Entry<String, String> m : map.entrySet()) { nvps.add(new BasicNameValuePair(m.getKey(), m.getValue())); } StringEntity entity; try { entity = new UrlEncodedFormEntity(nvps, HTTP.UTF_8); post.setEntity(entity); post.setHeader("Content-Type", contextType); HttpResponse response = httpClient.execute(post); statusCode = response.getStatusLine().getStatusCode(); System.out.println(statusCode); if (statusCode != 200) { System.out.println("error quest"); } } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { post.abort(); } return statusCode; } class postThread implements Runnable { private MultiThreadedHttpConnection m = null; private Map<String, String> map = null; public postThread(MultiThreadedHttpConnection m, Map<String, String> map) { this.m = m; this.map = map; } @Override public void run() { m.sendDataByPost(map); } } public static void main(String[] args) { for (int i = 0; i < 10000; i++) { Map<String, String> map = new HashMap<String, String>(); map.put("vcode", 1 + ""); map.put("sid", i + ""); MultiThreadedHttpConnection.getInstance().httpAsyncSendByMap(map); } } }
每个线程单独使用 HttpClient 一样超时。
我今天也遇到了,原因是你请求的是同一个服务器下的不同页面,httpclient在你和服务器之间建立了一条路由,这个路由的最大并发连接数是2,所以当你开启多个线程并发请求的时候,就会出现连接不够用或者连接超时的问题,解决方法是这样的(红色为重点): HttpParams params = new BasicHttpParams(); /* 从连接池中取连接的超时时间 */ ConnManagerParams.setTimeout(params, 10000); /* 连接超时 */ HttpConnectionParams.setConnectionTimeout(params, 20000); /* 请求超时 */ HttpConnectionParams.setSoTimeout(params, 40000); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory .getSocketFactory())); PoolingClientConnectionManager cm = new PoolingClientConnectionManager( schemeRegistry); cm.setMaxTotal(10); HttpHost localhost = new HttpHost("locahost", 80);
cm.setMaxPerRoute(new HttpRoute(localhost), 50); cm.setDefaultMaxPerRoute(20); final HttpClient httpClient = new DefaultHttpClient(cm, params);
cm.setMaxTotal(50);
HttpClient httpclient = new DefaultHttpClient(cm);
package com.kanesoft.method.httppost;import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HTTP;public class MultiThreadedHttpConnection {
private static HttpClient httpClient;
private static final String contextType = "text/xml;charset=UTF-8";
private static ExecutorService es = Executors.newFixedThreadPool(10);
private static MultiThreadedHttpConnection mthc = new MultiThreadedHttpConnection();
private static String url = "http://localhost:8000/2.php";
private static int maxTotal = 300;
private static int maxPerRout = 200;
private static int connecttimeOut = 10000;
private static int readTimeOut = 5000; static {
ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager();
cm.setMaxTotal(maxTotal);
cm.setDefaultMaxPerRoute(maxPerRout); HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params, connecttimeOut);
HttpConnectionParams.setSoTimeout(params, readTimeOut); httpClient = new DefaultHttpClient(cm, params); } private MultiThreadedHttpConnection() { } public static MultiThreadedHttpConnection getInstance() {
return mthc;
} public void httpAsyncSendByMap(final Map<String, String> map) {
es.execute(new postThread(mthc, map));
} private int sendDataByPost(Map<String, String> map) {
Integer statusCode = -1;
HttpPost post = new HttpPost(url);
List<NameValuePair> nvps = new ArrayList<NameValuePair>();
for (Map.Entry<String, String> m : map.entrySet()) {
nvps.add(new BasicNameValuePair(m.getKey(), m.getValue()));
}
StringEntity entity;
try {
entity = new UrlEncodedFormEntity(nvps, HTTP.UTF_8);
post.setEntity(entity);
post.setHeader("Content-Type", contextType);
HttpResponse response = httpClient.execute(post);
statusCode = response.getStatusLine().getStatusCode();
System.out.println(statusCode);
if (statusCode != 200) {
System.out.println("error quest");
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
post.abort();
} return statusCode;
} class postThread implements Runnable {
private MultiThreadedHttpConnection m = null;
private Map<String, String> map = null; public postThread(MultiThreadedHttpConnection m, Map<String, String> map) {
this.m = m;
this.map = map;
} @Override
public void run() {
m.sendDataByPost(map);
}
} public static void main(String[] args) {
for (int i = 0; i < 10000; i++) {
Map<String, String> map = new HashMap<String, String>();
map.put("vcode", 1 + "");
map.put("sid", i + "");
MultiThreadedHttpConnection.getInstance().httpAsyncSendByMap(map);
}
}
}
HttpParams params = new BasicHttpParams();
/* 从连接池中取连接的超时时间 */
ConnManagerParams.setTimeout(params, 10000);
/* 连接超时 */
HttpConnectionParams.setConnectionTimeout(params, 20000);
/* 请求超时 */
HttpConnectionParams.setSoTimeout(params, 40000);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", 80, PlainSocketFactory
.getSocketFactory()));
PoolingClientConnectionManager cm = new PoolingClientConnectionManager(
schemeRegistry);
cm.setMaxTotal(10);
HttpHost localhost = new HttpHost("locahost", 80);
cm.setMaxPerRoute(new HttpRoute(localhost), 50);
cm.setDefaultMaxPerRoute(20);
final HttpClient httpClient = new DefaultHttpClient(cm, params);