SocketInputStream.socketRead0 导致线程hangs的解决方案
来源:互联网 发布:程序员辛苦吗 编辑:程序博客网 时间:2024/06/05 20:39
前言
先声明,这里我没有试图去列举所有出现这种问题的情况,只针对我自己做过的项目遇到的问题。
问题代码如下:
首先通过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>```javapublic static class IdleConnectionMonitorThread extends Thread { private final HttpClientConnectionManager connMgr; private volatile boolean shutdown; public IdleConnectionMonitorThread(HttpClientConnectionManager connMgr) { super(); this.connMgr = connMgr; } @Override public void run() { try { while (!shutdown) { synchronized (this) { wait(5000); // Close expired connections connMgr.closeExpiredConnections(); // Optionally, close connections // that have been idle longer than 30 sec connMgr.closeIdleConnections(30, TimeUnit.SECONDS); } } } catch (InterruptedException ex) { // terminate } } public void shutdown() { shutdown = true; synchronized (this) { notifyAll(); } }}
0 0
- SocketInputStream.socketRead0 导致线程hangs的解决方案
- 解决Java从MySQL读取大量数据时卡在SocketInputStream.socketRead0的问题
- 应用初始化时mysql hold在SocketInputStream.socketRead0(Native Method)问题
- 【listener hangs】监听hangs,导致新的连接无法连接数据库
- socket连接代理socketRead0(Native Method) 线程阻塞处理
- SocketInputStream 分析
- 线程安全问题的解决方案
- 关于Bitmap 导致的OOM 解决方案
- Bitmap导致的OOM 终极解决方案
- GameProtectNet导致电脑蓝屏的尝试解决方案
- CFileDialog导致程序崩溃的解决方案
- Bitmap导致的OOM 终极解决方案
- Selinux导致的Varnish 503错误解决方案
- Bitmap导致的OOM 一些解决方案
- iOS 来电 导致布局变化的解决方案
- win10 explorer导致闪屏的解决方案
- GCD导致死锁的原因和解决方案
- Android Handler导致内存泄漏的解决方案
- SDUT oj 数据结构实验之二叉树三:统计叶子数
- javase重新开始系列之基础类型与运算符
- Android控件设置——动态View的drawableLeft/ drawableRight/drawableTop/drawableBottom
- maven仓库--私服(Nexus的配置使用)
- listview优化
- SocketInputStream.socketRead0 导致线程hangs的解决方案
- 标签入门
- Map转json是如何保证顺序以及Gson的单例化
- Symfony之components--第一章:如何安装symfony的components
- 凸包模板!!
- js获取url参数值的两种方式
- Google vr sdk的使用
- java web mvc开发模式
- 数据流中的中位数