java InputStream 关于read阻塞的问题讨论

本文探讨了Socket流与文件流的区别,特别是在Socket流不关闭时可能遇到的问题。此外,还深入分析了不同read方法的使用场景及注意事项,特别关注了在特定条件下可能出现的阻塞现象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://topic.youkuaiyun.com/u/20090304/15/a3df12fd-1896-4a17-bedc-cb863c955ecc.html

 

http://topic.youkuaiyun.com/u/20080620/11/478e7d71-e92a-4aca-8156-c9cfcb401bef.html?341823992

 

http://topic.youkuaiyun.com/u/20080626/09/18db2301-f672-4ec8-aaa8-bf8c75489893.html

 

 

过了半年再看自己这个帖子,发现仍然有些问题。
其实就两点,
1,socket流不关闭。socket流和文件流不太一样,文件流很容易知道文件末尾,到了文件末尾,直接就把流close掉就OK了。但是socket流不一样,你无法知道它什么时候到末尾,所以连接一直保持着,流也一直保持阻塞状态。即使用了带参数的read方法,返回了有效数据,但其实流仍然没有关闭,处于阻塞状态。

2,关于read的带参和不带参方法。当时迷惑主要就在两个read方法的结果不一样。最后还是要追溯到socketRead0这个本地方法,API上说这个方法

在输入数据可用、检测到文件末尾或者抛出异常前,此方法一直阻塞。

当我用字节读取的时候,不是可以用while((num = in.read(by)) != -1)这种情况么,当我们定义的by字节数组的长度的长度为1024,但当数据源的长度刚好为1024的倍数时,那么这样的情况是会阻塞的



转自:http://blog.youkuaiyun.com/dagouaofei/article/details/3962525

### Java `InputStream.read()` 方法阻塞的原因 `InputStream.read()` 方法会在没有可用字节时进入等待状态直到有数据到达或流关闭为止[^1]。当调用该方法而底层资源(例如套接字)没有任何待读取的数据时,当前线程会被挂起并处于阻塞状态。 对于基于TCP协议的Socket通信来说,在接收端通过`InputStream`尝试读取来自发送端的消息时如果对方尚未完成写入操作,则本地进程中的读取动作就会一直等待下去直至满足条件或者发生错误情况如连接中断等[^4]。 另外值得注意的是,即使存在某些情况下确实进行了所谓的“发送”,但如果实际传输的内容为空字符串(`""`)的话,那么接收侧依旧无法获取到有效的载荷信息从而导致看似无休止地停滞不前的现象出现。 #### 解决方案概述 为了防止不必要的长时间延迟甚至永久性的卡顿现象的发生,可以采取如下几种措施: - **设置超时时间** 可以为关联着特定通道实例的对象设定最大允许停留期限以便于在网络状况不佳或者其他异常情形下能够及时做出响应而不是无限期地持续监听下去。这可以通过配置对应的socket选项实现,比如SO_TIMEOUT参数用于指定以毫秒计的最大等候周期长度[^2]。 ```java // 设置读取超时时间为5秒钟 socket.setSoTimeout(5000); ``` - **优化消息结构设计** 应避免直接传递未经处理过的原始字符序列作为通讯载体的一部分;相反应当采用更加严谨的方式来构建报文体裁——譬如附加定界符或是规定确切大小限制等等手段确保每一帧都能被清晰识别出来进而减少误判的可能性。 - **捕获并妥善处置异常事件** 当遇到由上述调整所引发的各种意外状况之时,务必要编写好相应的捕捉逻辑来保障整个应用程序不至于因为单次失败就彻底崩溃掉而是可以选择重试机制或者是记录日志之后优雅退出[^3]。 ```java try { int bytesRead = inputStream.read(buffer); } catch (InterruptedIOException e) { System.out.println("Read timed out"); } catch (IOException e) { // Handle other possible I/O errors... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值