美文网首页Java之旅Java 杂谈
Java BIO改良(伪异步IO)

Java BIO改良(伪异步IO)

作者: 直到世界的尽头_yifan | 来源:发表于2018-01-06 22:23 被阅读2次

    请先移步查看《Java 传统的BIO编程》

    我们将客户端请求投递到线程池中进行处理,JDK线程池维护一个消息队列和N个活跃线程,对消息队列中的任务进行处理,由于线程池可以设置对队列的大小和最大线程数,因此占用的资源是可控的,无论多少个客户端并发访问,都不会导致资源的耗尽而宕机。

    弊端分析:由于底层通信依然采用同步阻塞队列,因此无法从根本上解决问题。

    Java InputStream:

    public int read(byte b[]) throws IOException {

    //This method blocks until input data is available, end of file is detected, or an exception is thrown.

            return read(b, 0, b.length);

        }

    当对Socket输入流进行读取操作的时候,它会一直阻塞下去,直到发生下面3种事件:

    (1)有数据可读

    (2)可用数据已经读取完毕

    (3)发生空指针或者IO异常

    这就意味着当发送请求或者应答消息比较缓慢,或者网络传输缓慢时,读取输入流一方的通信线程将被长时间阻塞,如果一方要60S才能将数据读取完毕,读取一方的IO线程将会被阻塞60S,在此期间,其他消息只能在消息队列中排队。

    当调用OutputStream的write方法写输出流的时候,它将会被阻塞直到所有要发送的字节全部写入完毕,或者发生异常。

    伪异步IO无法从根本上解决同步IO导致的通信线程阻塞问题,下面我们分析一下通信对方返回应答时间过长会引起的级联故障。

    1.服务器处理缓慢,返回应答消息耗费60S,平均只要10S

    2.采用伪异步IO线程正在读取故障服务节点的响应,由于读取输入流是阻塞的,它将会被

    阻塞60S

    3.假设所有可用的线程都会被故障服务器阻塞,那后续的IO消息都将在队列中排队

    4.由于线程池采用阻塞队列实现,当队列满了之后,后续入队列的操作将会被阻塞

    5.由于前端只有一个ACCEPTOR线程接受客户端接入,它被阻塞在线程池的同步阻塞队列之后,新的客户端请求消息将会被拒绝,客户端发生大量的连接超时

    6.由于几乎所有的连接都超时,调用者会认为系统已经崩溃,无法接受新的请求消息

    如何,Java NIO将会给出答案!!!

    相关文章

      网友评论

        本文标题:Java BIO改良(伪异步IO)

        本文链接:https://www.haomeiwen.com/subject/zejunxtx.html