优雅代码08-构建自己的连接池
Posted Seal_lee
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了优雅代码08-构建自己的连接池相关的知识,希望对你有一定的参考价值。
【优雅代码】08-构建自己的连接池
欢迎关注b站账号/公众号【六边形战士夏宁】,一个要把各项指标拉满的男人。该文章已在github目录收录。
屏幕前的大帅比和大漂亮如果有帮助到你的话请顺手点个赞、加个收藏这对我真的很重要。别下次一定了,都不关注上哪下次一定。
- 视频讲解
- 可直接运行的完整代码
- 上一篇spring下的优秀工具类
- 下一篇idea断点、插件、模板合集
1.背景
线程池的优势自不必多说,连接池和线程池有着众多相通之处,比较常见的连接池有druid、jedis等,但若是某些自研数据库等该如何构建自己的连接池就成问题。笔者使用http这一工具进行构建,可以对比效率差异。核心包为common-pool2
2.构建对象工厂
public class HttpCoonFactory extends BasePooledObjectFactory<HttpClient>
@Override
public HttpClient create() throws Exception
// 和线程池一样的设计思路创建对象
return HttpClients.createDefault();
@Override
public PooledObject<HttpClient> wrap(HttpClient httpClient)
// 和线程池一样的设计思路,包装对象
return new DefaultPooledObject<HttpClient>(httpClient);
3.定制化参数
public class HttpPoolConfig extends GenericObjectPoolConfig
public HttpPoolConfig()
// 这里的配置和其它连接池基本一致,一脉相承的设计思路
setMinIdle(5);
setTestOnBorrow(true);
setMaxTotal(50);
4.构建连接池
public class HttpPoolManager extends GenericObjectPool<HttpClient>
private static HttpPoolManager httpPoolManager = new HttpPoolManager();
public static HttpPoolManager getInstance()
// 将单例暴露出去
return httpPoolManager;
private HttpPoolManager()
// 将配置注入到连接池内
super(new HttpCoonFactory(), new HttpPoolConfig());
5.构建工具类
@Slf4j
public class HttpUtil
/**
* 发送get方法已改造成使用连接池
* @param url
* @return
*/
public static String sendGet(String url)
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(RequestConfig.custom()
.setConnectTimeout(3000)
.setConnectionRequestTimeout(3000)
.setSocketTimeout(3000)
.build());
CloseableHttpClient httpClient = null;
try
httpClient = (CloseableHttpClient) HttpPoolManager.getInstance().borrowObject();
try
@Cleanup CloseableHttpResponse response = httpClient.execute(httpGet);
HttpEntity entity = response.getEntity();
if (entity != null)
return EntityUtils.toString(entity);
catch (IOException e)
log.warn(String.format("%s:%s",
Thread.currentThread().getStackTrace()[1].getMethodName(),
e.getMessage()), e);
catch (Exception e)
log.warn(String.format("%s:%s",
Thread.currentThread().getStackTrace()[1].getMethodName(),
e.getMessage()), e);
finally
HttpPoolManager.getInstance().returnObject(httpClient);
return "";
/**
* 发送post方法已改造成使用连接池
* @param url
* @return
*/
public static String sendPost(String url, Map<String,String> paramsMap,Map<String, String> headMap)
List<NameValuePair> formParams = new ArrayList<>();
if(MapUtils.isNotEmpty(paramsMap))
for (Map.Entry<String, String> entry : paramsMap.entrySet())
formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(RequestConfig.custom()
.setConnectTimeout(3000)
.setConnectionRequestTimeout(3000)
.setSocketTimeout(3000)
.build());
if(MapUtils.isNotEmpty(headMap))
for (Map.Entry<String, String> entry : headMap.entrySet())
httpPost.setHeader(entry.getKey(), entry.getValue());
try
httpPost.setEntity(new UrlEncodedFormEntity(formParams, "utf-8"));
@Cleanup CloseableHttpClient httpClient = HttpClients.createDefault();
@Cleanup CloseableHttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
if (entity != null)
return EntityUtils.toString(entity);
catch (IOException e)
log.warn(String.format("%s:%s",
Thread.currentThread().getStackTrace()[1].getMethodName(),
e.getMessage()), e);
return "";
public static String sendPostJson(String url,String param,Map<String, String> headMap)
StringEntity entity = new StringEntity(param,"utf-8");
entity.setContentType(MediaType.APPLICATION_JSON_VALUE);
entity.setContentEncoding("utf-8");
HttpPost httpPost = new HttpPost(url);
httpPost.setConfig(RequestConfig.custom()
.setConnectTimeout(3000)
.setConnectionRequestTimeout(3000)
.setSocketTimeout(3000)
.build());
if(MapUtils.isNotEmpty(headMap))
for (Map.Entry<String, String> entry : headMap.entrySet())
httpPost.setHeader(entry.getKey(), entry.getValue());
try
httpPost.setEntity(entity);
@Cleanup CloseableHttpClient httpClient = HttpClients.createDefault();
@Cleanup CloseableHttpResponse response = httpClient.execute(httpPost);
HttpEntity entityResukt = response.getEntity();
if (entityResukt != null)
return EntityUtils.toString(entityResukt);
catch (IOException e)
log.warn(String.format("%s:%s",
Thread.currentThread().getStackTrace()[1].getMethodName(),
e.getMessage()), e);
return "";
/**
*
* @author seal 876651109@qq.com
* @date 2020/6/4 7:23 PM
*/
public static String postFile(InputStream stream,String fileName,String requestUrl)
try
URL url = new URL(requestUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(true);
conn.setChunkedStreamingMode(1024 * 10000);
conn.setRequestProperty("Content-Type", MediaType.MULTIPART_FORM_DATA_VALUE);
@Cleanup OutputStream out = new DataOutputStream(conn.getOutputStream());
IOUtils.copy(stream,out);
catch (ProtocolException e)
e.printStackTrace();
catch (MalformedURLException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
return "";
6.使用及对比
public static void main(String[] args)
String url = "http://www.baidu.com";
StopWatch stopWatch = new StopWatch();
stopWatch.start("pool");
for (int i = 0; i < 100; i++)
sendGet(url);
stopWatch.stop();
stopWatch.start("common");
for (int i = 0; i < 100; i++)
HttpGet httpGet = new HttpGet(url);
httpGet.setConfig(RequestConfig.custom()
.setConnectTimeout(3000)
.setConnectionRequestTimeout(3000)
.setSocketTimeout(3000)
.build());
try (CloseableHttpClient httpclient = HttpClients.createDefault())
httpclient.execute(httpGet).getEntity();
catch (IOException e)
e.printStackTrace();
stopWatch.stop();
System.out.println(stopWatch.prettyPrint());
- 结果如下,用连接池快了一倍,好处大大地
---------------------------------------------
ns % Task name
---------------------------------------------
1698114024 031% pool
3696532228 069% common
以上是关于优雅代码08-构建自己的连接池的主要内容,如果未能解决你的问题,请参考以下文章
newCacheThreadPool()newFixedThreadPool()newScheduledThreadPool()newSingleThreadExecutor()自定义线程池(代码片段