为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

汪汪一只猫 2019-05-08 12:56:57
有这么一个线程类(extendsThread)run方法中有如下代码while(true){Socketsocket=null;GZIPInputStreamgzis=null;ObjectInputStreamois=null;try{socket=newSocket(IP,PORT);gzis=newGZIPInputStream(socket.getInputStream());ois=newObjectInputStream(gzis);Mapresult=(Map)ois.readObject();doSomeBuziness(result);}catch(Exceptione){log.error(...);}finally{//cleanworkheresleep(1000);}}即线程启动后每隔1秒从Socket服务端接收数据然后对接收到的数据做些业务逻辑处理突然发现数据好像一直没有更新通过jstack命令可知该线程已经挂起了"Thread-5"daemonprio=10tid=0x00002b54800cd000nid=0x691frunnable[0x00002b5433be7000]java.lang.Thread.State:RUNNABLEatjava.net.SocketInputStream.socketRead0(NativeMethod)atjava.net.SocketInputStream.read(SocketInputStream.java:152)atjava.net.SocketInputStream.read(SocketInputStream.java:122)atjava.util.zip.InflaterInputStream.fill(InflaterInputStream.java:238)atjava.util.zip.InflaterInputStream.read(InflaterInputStream.java:158)atjava.util.zip.GZIPInputStream.read(GZIPInputStream.java:116)问:为什么线程都挂起了还是RUNNABLE状态呢?不是BLOCKED状态呢?这种挂起的底层机制是什么?如对应什么系统命令和下面等待锁释放导致线程挂起的区别是什么(底层机制有什么不同)staticsynchronizedvoidfoo(){Thread.sleep(10*60*1000);}如有一个加了同步块的foo方法两个线程都去调用这个foo方法其中一个会被阻塞"pool-1-thread-2"prio=5tid=0x00007f9ed00a5000nid=0x5503waitingformonitorentry[0x00007000079c7000]java.lang.Thread.State:BLOCKED(onobjectmonitor)atcom.demo.LockDemo.foo(LockDemo.java:24)-waitingtolock(ajava.lang.Classforcom.demo.LockDemo)atcom.demo.LockDemo$1.run(LockDemo.java:15)atjava.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471)针对Socketread的这种挂起不想重启应用有什么办法可以人工显式结束这种挂起吗?atjava.net.SocketInputStream.socketRead0(NativeMethod)如通过命令行显式杀死这个socket这样的话可以抛个异常被捕获然后休眠一秒可以继续往下走了不会卡住不动了
查看完整描述

2 回答

?
慕桂英4014372

TA贡献1871条经验 获得超13个赞

你应该好好JDK关于线程状态的文档java.lang.Thread.State
publicenumState{
/**
*Threadstateforathreadwhichhasnotyetstarted.
*/
NEW,
/**
*Threadstateforarunnablethread.Athreadintherunnable
*stateisexecutingintheJavavirtualmachinebutitmay
*bewaitingforotherresourcesfromtheoperatingsystem
*suchasprocessor.
*/
RUNNABLE,
/**
*Threadstateforathreadblockedwaitingforamonitorlock.
*Athreadintheblockedstateiswaitingforamonitorlock
*toenterasynchronizedblock/methodor
*reenterasynchronizedblock/methodaftercalling
*{@linkObject#wait()Object.wait}.
*/
BLOCKED,
/**
*Threadstateforawaitingthread.
*Athreadisinthewaitingstateduetocallingoneofthe
*followingmethods:
*
    *
  • {@linkObject#wait()Object.wait}withnotimeout
  • *
  • {@link#join()Thread.join}withnotimeout
  • *
  • {@linkLockSupport#park()LockSupport.park}
  • *
*
*

Athreadinthewaitingstateiswaitingforanotherthreadto

*performaparticularaction.
*
*Forexample,athreadthathascalledObject.wait()
*onanobjectiswaitingforanotherthreadtocall
*Object.notify()orObject.notifyAll()on
*thatobject.AthreadthathascalledThread.join()
*iswaitingforaspecifiedthreadtoterminate.
*/
WAITING,
/**
*Threadstateforawaitingthreadwithaspecifiedwaitingtime.
*Athreadisinthetimedwaitingstateduetocallingoneof
*thefollowingmethodswithaspecifiedpositivewaitingtime:
*
    *
  • {@link#sleepThread.sleep}
  • *
  • {@linkObject#wait(long)Object.wait}withtimeout
  • *
  • {@link#join(long)Thread.join}withtimeout
  • *
  • {@linkLockSupport#parkNanosLockSupport.parkNanos}
  • *
  • {@linkLockSupport#parkUntilLockSupport.parkUntil}
  • *
*/
TIMED_WAITING,
/**
*Threadstateforaterminatedthread.
*Thethreadhascompletedexecution.
*/
TERMINATED;
}
RUNNABLE状态指的是,线程正在JVM中运行,但是它们需要等待来自操作系统的资源,比如说CPU资源,这里当然是网络资源,所以它本该就是RUNNABLE的。BLOCKED状态,专门指的是线程正在等待内置锁的过程。WAITING说明线程正在等待另一个线程的特定操作。
想要结束这种等待,要么给与线程所需要的网络资源(这种控制不了),要么直接关闭Socket,或者调用interrupt方法(其实底层也是关闭Socket,可以看看interrupt的API文档)。
                            
查看完整回答
反对 回复 2019-05-08
  • 2 回答
  • 0 关注
  • 601 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信