有这么一个线程类(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 这样的话可以抛个异常被捕获 然后休眠一秒 可以继续往下走了 不会卡住不动了
你应该好好
JDK
关于线程状态的文档java.lang.Thread.State
RUNNABLE
状态指的是,线程正在JVM
中运行,但是它们需要等待来自操作系统的资源
,比如说CPU
资源,这里当然是网络资源,所以它本该就是RUNNABLE
的。BLOCKED
状态,专门指的是线程正在等待内置锁的过程。WAITING
说明线程正在等待另一个线程的特定操作。想要结束这种等待,要么给与线程所需要的网络资源(这种控制不了),要么直接关闭
Socket
,或者调用interrupt
方法(其实底层也是关闭Socket
,可以看看interrupt
的API
文档)。