关于Socket read挂起的一些疑问?
有这么一个线程类(extends Thread)run方法中有如下代码
while(true) {
Socket socket = null;
GZIPInputStream gzis = null;
ObjectInputStream ois = null;
try {
socket = new Socket(IP, PORT);
gzis = new GZIPInputStream(socket.getInputStream());
ois = new ObjectInputStream(gzis);
Map<Integer, Object> result = (Map<Integer, Object>) ois.readObject();
doSomeBuziness(result);
} catch(Exception e) {
log.error(...);
} finally {
// clean work here
sleep(1000);
}
}
即线程启动后 每隔1秒 从Socket服务端接收数据 然后对接收到的数据做些业务逻辑处理
突然发现数据好像一直没有更新 通过jstack
命令 可知该线程已经挂起了
"Thread-5" daemon prio=10 tid=0x00002b54800cd000 nid=0x691f runnable [0x00002b5433be7000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:152)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at java.util.zip.InflaterInputStream.fill(InflaterInputStream.java:238)
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)
at java.util.zip.GZIPInputStream.read(GZIPInputStream.java:116)
问:
- 为什么线程都挂起了 还是
RUNNABLE
状态呢? 不是BLOCKED
状态呢? - 这种挂起的底层机制是什么? 如对应什么系统命令 和下面等待锁释放导致线程挂起的区别是什么(底层机制有什么不同)
static synchronized void foo() {
Thread.sleep(10*60*1000);
}
如有一个加了同步块的foo方法 两个线程都去调用这个foo方法 其中一个会被阻塞
"pool-1-thread-2" prio=5 tid=0x00007f9ed00a5000 nid=0x5503 waiting for monitor entry [0x00007000079c7000]
java.lang.Thread.State: BLOCKED (on object monitor)
at com.demo.LockDemo.foo(LockDemo.java:24)
- waiting to lock <0x00000007aae446d0> (a java.lang.Class for com.demo.LockDemo)
at com.demo.LockDemo$1.run(LockDemo.java:15)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)
- 针对
Socket read
的这种挂起 不想重启应用 有什么办法可以人工显式结束这种挂起吗?
at java.net.SocketInputStream.socketRead0(Native Method)
如 通过命令行显式杀死这个socket 这样的话可以抛个异常被捕获 然后休眠一秒 可以继续往下走了 不会卡住不动了
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我觉得设置 socket 的超时时间比较合适, 如
如此, 当 socket read 在超过 60秒没有收到数据时, 将抛出 SocketException 异常.
另外, 在 try finally 中应释放资源(关闭 socket).
"针对Socket read的这种挂起 不想重启应用 有什么办法可以人工显式结束这种挂起吗?"
1.得到socket对应的
fileDescriptor
2.通过gdb显式关闭socket
参考文档:
https://superuser.com/questio...
你应该好好
JDK
关于线程状态的文档java.lang.Thread.State
RUNNABLE
状态指的是,线程正在JVM
中运行,但是它们需要等待来自操作系统的资源
,比如说CPU
资源,这里当然是网络资源,所以它本该就是RUNNABLE
的。BLOCKED
状态,专门指的是线程正在等待内置锁的过程。WAITING
说明线程正在等待另一个线程的特定操作。想要结束这种等待,要么给与线程所需要的网络资源(这种控制不了),要么直接关闭
Socket
,或者调用interrupt
方法(其实底层也是关闭Socket
,可以看看interrupt
的API
文档)。