记Java代码的一次线程之旅
0.前言
我很纳闷儿,为啥我没有开启多线程,但是程序却最后跑出了多线程,正在我十分不解时,我观察intellij的标准输出察觉出有些规律可循。日志如下:
1.日志
22:36:07.012 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:07.012 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:12.013 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:12.013 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
···
22:36:17.014 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:17.014 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:17.315 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:17.315 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:22.014 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:22.014 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:22.316 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:22.316 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
···
22:36:27.014 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:27.014 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:27.317 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:27.317 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:27.517 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:27.517 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:32.015 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:32.015 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:32.317 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:32.317 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:32.517 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:32.517 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
···
22:36:47.016 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:47.016 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:47.319 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:47.319 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:47.519 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:47.519 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:47.716 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:47.716 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:47.908 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:47.908 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:52.017 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:52.017 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:52.319 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:52.319 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:52.520 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:52.520 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:52.716 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:52.716 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:52.909 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:52.909 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
···
22:36:57.018 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:57.018 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:57.320 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:57.320 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:57.520 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:57.520 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:57.716 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:57.716 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:57.910 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:57.910 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:36:58.088 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:36:58.088 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:02.018 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:02.018 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:02.320 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:02.320 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:02.520 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:02.520 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:02.717 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:02.717 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:02.911 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:02.911 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:03.089 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:03.089 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
····
22:37:07.019 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:07.019 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:07.019 [Thread-0] DEBUG o.a.h.i.c.DefaultManagedHttpClientConnection - http-outgoing-0: Close connection
22:37:07.321 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:07.321 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:07.521 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:07.521 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:07.718 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:07.718 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:07.911 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:07.911 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:08.090 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:08.090 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:08.269 [Thread-6] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:08.269 [Thread-6] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:12.020 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:12.020 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:12.321 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:12.321 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:12.321 [Thread-1] DEBUG o.a.h.i.c.DefaultManagedHttpClientConnection - http-outgoing-1: Close connection
22:37:12.521 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:12.521 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:12.718 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:12.718 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:12.911 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:12.911 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:13.090 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:13.090 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:13.269 [Thread-6] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:13.269 [Thread-6] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
···
22:37:17.020 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:17.020 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:17.322 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:17.322 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:17.522 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:17.522 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:17.719 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:17.719 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:17.911 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:17.911 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:18.091 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:18.091 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:18.270 [Thread-6] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:18.270 [Thread-6] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:18.463 [Thread-7] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:18.463 [Thread-7] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:22.020 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:22.020 [Thread-0] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:22.323 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:22.323 [Thread-1] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:22.522 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:22.522 [Thread-2] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:22.719 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:22.719 [Thread-3] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:22.912 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:22.912 [Thread-4] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:23.092 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:23.092 [Thread-5] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:23.270 [Thread-6] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:23.270 [Thread-6] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
22:37:23.463 [Thread-7] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing expired connections
22:37:23.463 [Thread-7] DEBUG o.a.h.i.c.PoolingHttpClientConnectionManager - Closing connections idle longer than 60 SECONDS
2.思考
仔细发现,可以看到这个线程数按照1的数目递增,那么这个现象能够说明的原因就是:并不是因为设置了某个固定的线程数,而是因为某种特殊的原因导致多个线程在运行了。
接着,我就查看我的源代码,怀疑问题可能出现在while(true)循环中,其中代码如下:
public static void main(String[] args) {
while(true){
//testPutData();
String charset = "utf-8";
CsdnHtml csdnHtml = new CsdnHtml();
String[] result;
result = csdnHtml.getSpecificInfo(
"myCsdn",
"https://blog.csdn.net/liu16659",
"grade-box clearfix",
charset);
putCsdnData(result);
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
出现多线程的原因就是在这个while循环里。while循环中调用了putCsdnData(result)这个方法,查看这个方法
public static void putCsdnData(String [] data) {
OpentsdbClient client = new OpentsdbClient("http://192.168.211.4:4399");
long accessNumber = Long.parseLong(data[1]);
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm");
try {
Map tagMap = new HashMap();
tagMap.put("accessNumber", "cs");
client.putData(
"csdn",
DateTimeUtil.parse(sdf.format(date).toString(), "yyyyMMdd HH:mm"),
accessNumber,
tagMap);
} catch (Exception e) {
e.printStackTrace();
}
}
就会发现问题所在,因为每次调用一个putCsdnData()
方法时,都会new一个OpentsdbClient
的实例,这样每个实例都会使用一个线程【底层代码的实现】,最后慢慢累积成多个线程。
接着是,将代码修改成如下样子:
static OpentsdbClient client = new OpentsdbClient("http://192.168.211.4:4399");//使用static修饰
public static void putCsdnData(String [] data) {
long accessNumber = Long.parseLong(data[1]);
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd HH:mm");
try {
Map tagMap = new HashMap();
tagMap.put("accessNumber", "cs");
client.putData(
"csdn",
DateTimeUtil.parse(sdf.format(date).toString(), "yyyyMMdd HH:mm"),
accessNumber,
tagMap);
} catch (Exception e) {
e.printStackTrace();
}
}
最后,再次执行,即成了单线程,标准输出如下: