有這么一個線程類(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 這樣的話可以拋個異常被捕獲 然后休眠一秒 可以繼續往下走了 不會卡住不動了
3 回答

慕村225694
TA貢獻1880條經驗 獲得超4個贊
你應該好好JDK
關于線程狀態的文檔java.lang.Thread.State
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
RUNNABLE
狀態指的是,線程正在JVM
中運行,但是它們需要等待來自操作系統的資源
,比如說CPU
資源,這里當然是網絡資源,所以它本該就是RUNNABLE
的。BLOCKED
狀態,專門指的是線程正在等待內置鎖的過程。WAITING
說明線程正在等待另一個線程的特定操作。
想要結束這種等待,要么給與線程所需要的網絡資源(這種控制不了),要么直接關閉Socket
,或者調用interrupt
方法(其實底層也是關閉Socket
,可以看看interrupt
的API
文檔)。

哆啦的時光機
TA貢獻1779條經驗 獲得超6個贊
我覺得設置 socket 的超時時間比較合適, 如
socket = new Socket(IP, PORT);
socket.setSoTimeout(1000 * 60); // 讀操作的超時時間為 60 秒
如此, 當 socket read 在超過 60秒沒有收到數據時, 將拋出 SocketException 異常.
另外, 在 try finally 中應釋放資源(關閉 socket).
添加回答
舉報
0/150
提交
取消