关于Socket read挂起的一些疑问?

发布于 2022-09-11 17:48:49 字数 2247 浏览 23 评论 0

有这么一个线程类(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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夏末染殇 2022-09-18 17:48:49

我觉得设置 socket 的超时时间比较合适, 如

socket = new Socket(IP, PORT);
socket.setSoTimeout(1000 * 60);  // 读操作的超时时间为 60 秒

如此, 当 socket read 在超过 60秒没有收到数据时, 将抛出 SocketException 异常.

另外, 在 try finally 中应释放资源(关闭 socket).

别在捏我脸啦 2022-09-18 17:48:49

"针对Socket read的这种挂起 不想重启应用 有什么办法可以人工显式结束这种挂起吗?"
1.得到socket对应的fileDescriptor

# lsof -i:10013
COMMAND  PID USER   FD   TYPE    DEVICE SIZE/OFF NODE NAME
java    8264 root   11u  IPv4 225505792      0t0  TCP izuf6cj2o216xpzfzh1rioz:10013->114.246.74.218:55984 (ESTABLISHED)

2.通过gdb显式关闭socket

# gdb -p 8264
(gdb) call close(11)
(gdb) quit

参考文档:
https://superuser.com/questio...

一曲琵琶半遮面シ 2022-09-18 17:48:49

你应该好好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,可以看看interruptAPI文档)。

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文