1
xixinimei 2018-09-26 13:24:15 +08:00
这不是死锁,应该是执行 wait 没有被唤醒。
|
2
huxiweng OP @xixinimei 怎么会 wait 呢,啥事都没做,就用 okhttp 发送 http 请求,怎么这么多 wait 的,TCP 连接数不断上涨,感觉跟这 okhttp 有很大关系。
代码: /** * 向指定 URL 发送 POST 方法的请求 * * @param url 发送请求的 URL * @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。 * @return 所代表远程资源的响应结果 */ public static String sendPostOKHttp(String url, String param) { logger.info("sendPostOKHttp()"); OkHttpClient client = new OkHttpClient(); // 1.构建 RequestBody RequestBody body = RequestBody.create(MediaType.parse("text/xml;charset=UTF-8"),param); Request request = new Request.Builder().url(url).post(body).build(); Response response = null; try { response = client.newCall(request).execute(); return response.body().string(); } catch (IOException e) { e.printStackTrace(); } return ""; } /** * 处理 http 请求( GET/POST ) * * @param reqUrl 请求地址 * @param reqMethod 请求方式( GET/POST ) * @param outputStr 参数( JSON String ) * @return */ public static String httpReqOKHttp(String reqUrl, String reqMethod, String outputStr) { logger.info("httpReqOKHttp()"); String returnStr = ""; if ("POST".equalsIgnoreCase(reqMethod)) { MediaType JSON = MediaType.get("application/json; charset=utf-8"); OkHttpClient client = new OkHttpClient(); RequestBody body = RequestBody.create(JSON, outputStr); Request request = new Request.Builder().url(reqUrl).post(body).build(); Response response = null; try { response = client.newCall(request).execute(); returnStr = response.body().string(); } catch (IOException e) { e.printStackTrace(); logger.error(e.getStackTrace()); } } if ("GET".equalsIgnoreCase(reqMethod)) { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(reqUrl).build(); Response response = null; try { response = client.newCall(request).execute(); returnStr = response.body().string(); } catch (IOException e) { logger.error(e.getStackTrace()); } } return returnStr; } /** * 向指定 URL 发送 GET 方法的请求 * * @param url 发送请求的 URL * @return URL 所代表远程资源的响应结果 */ public static String sendGetOKHttp(String url) { logger.info("sendGetOKHttp()"); OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(url).build(); Response response = null; try { response = client.newCall(request).execute(); return response.body().string(); } catch (IOException e) { e.printStackTrace(); } return ""; } |
3
xixinimei 2018-09-26 13:57:35 +08:00
wait 的不是你的代码,是 okhttp 的 ConnectionPool,Okhttp 哪个版本?我看的 3.11.0 版本。是清除空闲连接的线程池在跑这段 runnable。每隔 5 分钟(也就是你线程堆栈里的 waitting 状态)执行一次。这个线程池中的线程都是 deamon 的。这个没有什么问题,不用关心。
|
4
xixinimei 2018-09-26 14:01:59 +08:00
有问题的是你的 OkHttpClient 实例创建太多,导致有很多线程池。。。。
|
5
huxiweng OP @xixinimei
okhttp-3.11.0.jar 应该是 3.11.0 版本 3 楼你说的我有点晕,意思是 jstack 打印的内容里的: "OkHttp ConnectionPool" daemon prio=10 tid=0x00007f5b2c300000 nid=0x752 in Object.wait() [0x00007f5af35f4000] java.lang.Thread.State: TIMED_WAITING (on object monitor) 是没有问题的是吗?可以不用管? 然后是我自己写的方法,调用一次 sendPostOKHttp()方法就创建一个 OkHttpClient,然后由于 OkHttpClient 对象太多,就有 N 个线程(还是线程池)?这样理解对吗? ***** 所以我的代码要改一下: 把 OkHttpClient client = new OkHttpClient();定义到类成员变量,然后每次使用这个对象调用剩下的代码? 这样理解对吗? |
6
xixinimei 2018-09-26 15:24:35 +08:00 1
OkHttpClient 所在类也是单实例的,就可以定义成其成员变量。
建议参考 OkHttpClient 文档,写得非常清楚。OkHttpClient 对象应该是单例的,原因就是每个 OkHttpClient 都有自己的 connection pool 和 thread pool |
7
huxiweng OP @xixinimei
改成下面单例,好像死锁了。。。 private static OkHttpClient okHttpClient = null; private HttpTool() { } public static OkHttpClient getInstance() { if (okHttpClient == null) { //加同步安全 synchronized (HttpTool.class) { if (okHttpClient == null) { //判空 为空创建实例 okHttpClient = new OkHttpClient(); } } } return okHttpClient; } jstack 日志: 2018-09-27 08:01:43 Full thread dump Java HotSpot(TM) 64-Bit Server VM (24.80-b11 mixed mode): "Attach Listener" daemon prio=10 tid=0x00007f5d1c001000 nid=0x11ba runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE "Okio Watchdog" daemon prio=10 tid=0x00007f5d14924800 nid=0x117c in Object.wait() [0x00007f5d20e12000] java.lang.Thread.State: TIMED_WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x00000007889c4fd8> (a java.lang.Class for okio.AsyncTimeout) at okio.AsyncTimeout$Companion.awaitTimeout$jvm(AsyncTimeout.kt:341) at okio.AsyncTimeout$Watchdog.run(AsyncTimeout.kt:228) - locked <0x00000007889c4fd8> (a java.lang.Class for okio.AsyncTimeout) "Java2D Disposer" daemon prio=10 tid=0x00007f5d1491e800 nid=0x110d in Object.wait() [0x00007f5d20131000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x0000000788ba7c48> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:135) - locked <0x0000000788ba7c48> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:151) at sun.java2d.Disposer.run(Disposer.java:145) at java.lang.Thread.run(Thread.java:745) "New I/O worker #8" prio=10 tid=0x00007f5d0c014000 nid=0x110c runnable [0x00007f5d2070b000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method) at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269) at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79) at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87) - locked <0x00000007fbf15d98> (a sun.nio.ch.Util$2) - locked <0x00000007fbf15d88> (a java.util.Collections$UnmodifiableSet) - locked <0x00000007fbf02948> (a sun.nio.ch.EPollSelectorImpl) at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98) at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:52) at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:208) at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:38) at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:102) at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) "New I/O worker #7" prio=10 tid=0x00007f5d0c011800 nid=0x110b runnable [0x00007f5d2080c000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method) at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269) at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79) at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87) - locked <0x000000078859c718> (a sun.nio.ch.Util$2) - locked <0x000000078859c708> (a java.util.Collections$UnmodifiableSet) - locked <0x000000078855fb30> (a sun.nio.ch.EPollSelectorImpl) at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98) at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:52) at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:208) at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:38) at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:102) at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) "New I/O worker #6" prio=10 tid=0x00007f5d0c010000 nid=0x110a runnable [0x00007f5d2090d000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method) at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269) at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79) at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87) - locked <0x00000007fbf0fe28> (a sun.nio.ch.Util$2) - locked <0x00000007fbf0fe18> (a java.util.Collections$UnmodifiableSet) - locked <0x00000007fbf0d818> (a sun.nio.ch.EPollSelectorImpl) at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98) at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:52) at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:208) at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:38) at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:102) at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) "New I/O worker #5" prio=10 tid=0x00007f5d0c003800 nid=0x1109 runnable [0x00007f5d20a0e000] java.lang.Thread.State: RUNNABLE at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method) at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:269) at sun.nio.ch.EPollSelectorImpl.doSelect(EPollSelectorImpl.java:79) at sun.nio.ch.SelectorImpl.lockAndDoSelect(SelectorImpl.java:87) - locked <0x00000007885c1230> (a sun.nio.ch.Util$2) - locked <0x00000007885c1220> (a java.util.Collections$UnmodifiableSet) - locked <0x00000007885b1078> (a sun.nio.ch.EPollSelectorImpl) at sun.nio.ch.SelectorImpl.select(SelectorImpl.java:98) at org.jboss.netty.channel.socket.nio.SelectorUtil.select(SelectorUtil.java:52) at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:208) at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:38) at org.jboss.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:102) at org.jboss.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:745) |