SocketInputStream.socketRead0 导致线程hangs的解决方案
前言
先声明,这里我没有试图去列举所有出现这种问题的情况,只针对我自己做过的项目遇到的问题。
问题代码如下:
首先通过HttpURLConnection创建链接:
URL url = new URL( servletUrl );HttpURLConnection connection = (HttpURLConnection)url.openConnection();trustModifier.relaxHostChecking( connection );connection.setDoOutput( true );connection.setRequestMethod( REQUEST_METHOD );
然后在执行了send之后,等待远端读取,并返回,注意这里的代码,用的是URLConnection,然后从socket上读取数据,并没有用到HttpURLConnection.getResonpseCode()
public void handleResponse( URLConnection connection ) throws IOException{try (BufferedReader connectionBuffer =new BufferedReader( new InputStreamReader( connection.getInputStream(), UTF_8 ) )){String response;while( (response = connectionBuffer.readLine()) != null ){logger.debug( response );}}}
当你的并发操作很多,线程切换很频繁,cpu load很高的时候,就会出现SocketInputStream.socketRead0的问题:
13:04:54,193 INFO [stdout] (EJB default - 1) at java.net.SocketInputStream.socketRead0(Native Method) ~[na:1.7.0_25]13:04:54,193 INFO [stdout] (EJB default - 1) at java.net.SocketInputStream.read(SocketInputStream.java:150) ~[na:1.7.0_25]13:04:54,193 INFO [stdout] (EJB default - 1) at java.net.SocketInputStream.read(SocketInputStream.java:121) ~[na:1.7.0_25]13:04:54,194 INFO [stdout] (EJB default - 1) at sun.security.ssl.InputRecord.readFully(InputRecord.java:442) ~[na:na]13:04:54,195 INFO [stdout] (EJB default - 1) at sun.security.ssl.InputRecord.read(InputRecord.java:480) ~[na:na]13:04:54,195 INFO [stdout] (EJB default - 1) at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:927) ~[na:na]13:04:54,196 INFO [stdout] (EJB default - 1) at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:884) ~[na:na]13:04:54,196 INFO [stdout] (EJB default - 1) at sun.security.ssl.AppInputStream.read(AppInputStream.java:102) ~[na:na]13:04:54,196 INFO [stdout] (EJB default - 1) at java.io.BufferedInputStream.fill(BufferedInputStream.java:235) ~[na:1.7.0_25]13:04:54,196 INFO [stdout] (EJB default - 1) at java.io.BufferedInputStream.read1(BufferedInputStream.java:275) ~[na:1.7.0_25]13:04:54,197 INFO [stdout] (EJB default - 1) at java.io.BufferedInputStream.read(BufferedInputStream.java:334) ~[na:1.7.0_25]13:04:54,197 INFO [stdout] (EJB default - 1) at sun.net.www.http.HttpClient.parseHTTPHeader(HttpClient.java:633) ~[na:na]13:04:54,197 INFO [stdout] (EJB default - 1) at sun.net.www.http.HttpClient.parseHTTP(HttpClient.java:579) ~[na:na]13:04:54,197 INFO [stdout] (EJB default - 1) at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1322) ~[na:na]13:04:54,197 INFO [stdout] (EJB default - 1) at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254) ~[na:na]
原因
使用HttpURLConnection的步骤是先实例化一个URL对象,通过URL的openConnection实例化HttpURLConnection对象。然后设置参数,注意此时并没有发生连接。真正发生连接是在获得流时即conn.getInputStream这一句时,这点跟TCP Socket是一样的。并非阻塞在ServerSocket.accept()而是阻塞在获取流。所以在获取流之前应该设置好所有的参数。特别是timeout参数。
**做个总结,进行远程通信时,在客户程序中,线程在以下情况可能进入阻塞状态:**请求与服务器建立连接时,即当线程执行Socket的带参数的构造方法,或执行Socket的connect()方法时,会进入阻塞状态,直到连接成功,此线程才从Socket的构造方法或connect()方法返回。
线程从Socket的输入流读入数据时,如果没有足够的数据,就会进入阻塞状态,直到读到了足够的数据,或者到达输入流的末尾,或者出现了异常,才从输入流的read()方法返回或异常中断。输入流中有多少数据才算足够呢?这要看线程执行的read()方法的类型:1. int read():只要输入流中有一个字节,就算足够。2. int read(byte[] buff):只要输入流中的字节数目与参数buff数组的长度相同就算足够。3. String readLine():只要输入流中有一行字符串,就算足够。值得注意的是InputStream类并没有readLine()方法,在过滤流BufferedReader类中才有此方法。线程向Socket的输出流写一批数据时,可能会进入阻塞状态,等到输出了所有的数据,或者出现异常,才从输出流的write()方法返回或异常中断。
当调用Socket的setSoLinger()方法设置了关闭Socket的延迟时间,那么当线程执行Socket的close()方法时,会进入阻塞状态,直到底层Socket发送完所有剩余数据,或者超过了setSoLinger()方法设置的延迟时间,才从close()方法返回。
在服务器程序中,线程在以下情况可能会进入阻塞状态:线程执行ServerSocket的accept()方法,等待客户的连接,直到接收到了客户连接,才从accept()方法返回。
线程从Socket的输入流读入数据时, 如果输入流没有足够的数据,就会进入阻塞状态。
线程向Socket的输出流写一批数据时,可能会进入阻塞状态,等到输出了所有的数据,或者出现异常,才从输出流的write()方法返回或异常中断。###解决方案
---
1, 通过setTimeout可以解决问题
```java
//设置connection timeout为3秒
connection.setConnectionTimeout(3 * 1000)
//设置read timeout为5秒
connection.setReadTimeout(5 * 1000)2,通过一个connection的监控线程,查询定时清除掉已经expired或者idle的链接。<div class="se-preview-section-delimiter"></div>```java
public static class IdleConnectionMonitorThread extends Thread {private final HttpClientConnectionManager connMgr;private volatile boolean shutdown;public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) {super();this.connMgr = connMgr;}@Overridepublic void run() {try {while (!shutdown) {synchronized (this) {wait(5000);// Close expired connectionsconnMgr.closeExpiredConnections();// Optionally, close connections// that have been idle longer than 30 secconnMgr.closeIdleConnections(30, TimeUnit.SECONDS);}}} catch (InterruptedException ex) {// terminate}}public void shutdown() {shutdown = true;synchronized (this) {notifyAll();}}}
SocketInputStream.socketRead0 导致线程hangs的解决方案相关推荐
- Java线上问题排障:Linux内核bug引发JVM死锁导致线程假死
Java本质上还是离不开操作系统,一来Java源码是用C/C++实现的,二来java进程还是需要依附于操作系统和硬件资源,有时候一些问题是操作系统级别导致的,下面的整个事件是源自一则真实的线上案例. ...
- SimpleDateFormat类的线程安全问题和解决方案
摘要:我们就一起看下在高并发下SimpleDateFormat类为何会出现安全问题,以及如何解决SimpleDateFormat类的安全问题. 本文分享自华为云社区<SimpleDateForm ...
- 为什么HashMap线程不安全?以及实现HashMap线程安全的解决方案
一.为什么HashMap线程不安全? 原著参考 1.JDK1.7 扩容引发的死循环和数据丢失 (1).当前jdk1.7版本的HashMap线程不安全主要是发生在扩容函数中,其中调用了HshMap的tr ...
- 导致线程死锁的原因?怎么解除线程死锁
欢迎大家关注我的公众号[老周聊架构],Java后端主流技术栈的原理.源码分析.架构以及各种互联网高并发.高性能.高可用的解决方案. 一.导致线程死锁的原因 多个线程同时被阻塞,它们中的一个或者全部都在 ...
- C# 在异步中使用HttpWebRequest出现的“正在终止线程”错误的解决方案
C# 在异步中使用HttpWebRequest出现的"正在终止线程"错误的解决方案 参考文章: (1)C# 在异步中使用HttpWebRequest出现的"正在终止线程& ...
- 因滚动条出现而导致页面晃动的解决方案
因滚动条出现而导致页面晃动的解决方案 这两天因为oa主页为了消除晃动的影响给body下的div加了一个{min-height:960},可是产品对底部出现的大片空白不满意,而且如果换了超大屏幕这个最小 ...
- Ubuntu下安装Wine可能导致假死问题解决方案
Ubuntu下安装Wine可能导致假死问题解决方案 出现问题 在使用Ubuntu使用apt-get install wine时,导致下载处于假死状态,不论将dpkg命令杀死,还是按照提示sudo ap ...
- java多线程安全解决方案_《Java多线程编程核心技术(第2版)》 —1.2.8 实例变量共享造成的非线程安全问题与解决方案...
1.2.8 实例变量共享造成的非线程安全问题与解决方案 自定义线程类中的实例变量针对其他线程可以有共享与不共享之分,这在多个线程之间交互时是很重要的技术点. 1.不共享数据的情况 不共享数据的情况如图 ...
- 谈谈spring-boot不同包结构下,同样的类名冲突导致服务启动失败解决方案
谈谈spring-boot不同包结构下,同样的类名冲突导致服务启动失败解决方案 参考文章: (1)谈谈spring-boot不同包结构下,同样的类名冲突导致服务启动失败解决方案 (2)https:// ...
最新文章
- 用gensim学习word2vec
- 【小练习】“表格”制作及答案
- rocm平台_痛击NV CUDA!AMD ROCm开放计算平台瓜熟蒂落
- istio api_Istio的网络API解释了
- linux ssh禁止用户访问任何目录,怎么限制远程ssh用户访问特定的文件
- json同一个参数不同类型_js基础之变量类型
- (转)【重磅】无监督学习生成式对抗网络突破,OpenAI 5大项目落地
- CentOS 7安装zabbix-agent 5.0报错:依赖检测失败:libpcre.so.0()(64bit)/获取GPG密钥失败解决
- mysql存储php数组_mysql数据库存储PHP数组、对象的方法
- 艺术字体图标设计软件Art Text 4 for Mac
- 水晶报表自定义函数进行代码重用 -日期大写
- 阿里云商标智能注册申请图文教程(亲踩坑)
- 自考CISSP信息分享
- 马未都说收藏:陶瓷篇-常见瓷器器形分类
- GB50016计算机房设计规定,为什么GB50016-2014《建筑设计防火规范》不包含防排烟系统实施规定?...
- OJ笔记 18939 最长单词
- AtCoder2362 - Splatter Painting - DFS+思维
- Lumerical官方案例、FDTD时域有限差分法仿真学习(九)——布拉格光栅(Bragg gratings)
- 扫描识别行驶证的软件技术
- 使用URLRewriter进行URL重写失效