美文网首页
Java NIO学习笔记 - 伪异步IO编程

Java NIO学习笔记 - 伪异步IO编程

作者: FX_SKY | 来源:发表于2017-03-20 23:35 被阅读71次

为了解决同步阻塞IO面临的一个链路需要一个线程处理的问题,后来有人对它的线程模型进行了优化,后端通过一个线程池来处理多个客户端的请求接入,形成客户端个数M:线程池最大线程数N的比例关系,其中M可以远远大于N,通过线程池可以灵活的调配线程资源,设置线程的最大值,防止由于海量并发接入导致线程耗尽。 下面,我们结合连接模型图和源码,对伪异步IO进行分析,看它是否能够解决同步阻塞IO面临的问题。

伪异步IO模型图

采用线程池和任务队列可以实现一种叫做伪异步的IO通信框架,它的模型图如下:

asyn-io-model.png

当有新的客户端接入的时候,将客户端的Socket封装成一个Task(该任务实现java.lang.Runnable接口)投递到后端的线程池中进行处理,JDK的线程池维护一个消息队列和N个活跃线程对消息队列中的任务进行处理。由于线程池可以设置消息队列的大小和最大线程数,因此,它的资源占用是可控的,无论多少个客户端并发访问,都不会导致资源的耗尽和宕机。 下面的小节,我们依然采用时间服务器程序,将其改造成伪异步IO时间服务器,然后通过对代码进行分析,找出其弊端。

伪异步式IO创建的TimeServer源码分析

我们对服务端代码进行一些改造,源码如下:

import com.bytebeats.jdk.bio.server.TimeServerHandler;
import com.bytebeats.jdk.bio2.TimeServerHandlerExecutor;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class TimeServer {

    /**
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        int port = 8080;
        if (args != null && args.length > 0) {
            try {
                port = Integer.valueOf(args[0]);
            } catch (NumberFormatException e) {
                // 采用默认值
            }
        }
        ServerSocket server = null;
        try {
            server = new ServerSocket(port);
            System.out.println("The time server is start in port : " + port);
            Socket socket = null;
            TimeServerHandlerExecutor singleExecutor = new TimeServerHandlerExecutor(
                    50, 10000);// 创建IO任务线程池
            while (true) {
                socket = server.accept();
                System.out.println("收到来自客户端的请求");
                singleExecutor.execute(new TimeServerHandler(socket));
            }
        } finally {
            if (server != null) {
                System.out.println("The time server close");
                server.close();
            }
        }
    }
}

伪异步IO的主函数代码发生了变化,我们首先创建一个时间服务器处理类的线程池,当接收到新的客户端连接的时候,将请求Socket封装成一个Task,然后调用线程池的execute方法执行,从而避免了每个请求接入都创建一个新的线程。 伪异步IO的TimeServerHandlerExecutor:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class TimeServerHandlerExecutor {

    private ExecutorService executor;

    public TimeServerHandlerExecutor(int maxPoolSize, int queueSize) {
        executor = new ThreadPoolExecutor(Runtime.getRuntime()
        .availableProcessors(), maxPoolSize, 120L, TimeUnit.SECONDS,
        new ArrayBlockingQueue(queueSize));
    }
    public void execute(java.lang.Runnable task) {
    executor.execute(task);
    }
}

由于线程池和消息队列都是有界的,因此,无论客户端并发连接数多大,它都不会导致线程个数过于膨胀或者内存溢出,相比于传统的一连接一线程模型,是一种改良。



伪异步IO通信框架采用了线程池实现,因此避免了为每个请求都创建一个独立线程造成的线程资源耗尽问题。但是由于它底层的通信依然采用同步阻塞模型,因此无法从根本上解决问题。

参考资料

《Netty 权威指南》—— 伪异步IO编程

相关文章

  • Java NIO学习笔记 - 伪异步IO编程

    为了解决同步阻塞IO面临的一个链路需要一个线程处理的问题,后来有人对它的线程模型进行了优化,后端通过一个线程池来处...

  • netty 入门杂谈

    java io 模型一共分为4种 传统IO 伪异步IO NIO AIO 介绍 netty是一个高性能,异步事件驱动...

  • Java IO快速入门

    网络IO实现方式分为BIO(阻塞IO)、线程池伪异步IO、NIO(非阻塞IO)、AIO(异步非阻塞IO); 异步、...

  • Reactor模式

    关键词:Reactor模式 IO NIO 阻塞 异步 阻塞/异步概念:读网络教科书 Java NIO和IO区...

  • java IO、NIO、AIO

    IO流(同步、阻塞) 、 NIO(同步、非阻塞) 、 NIO2(异步、非阻塞) 概述在我们学习Java的IO流之前...

  • nio

    参考文章 Java Nio Java NIO学习笔记 - NIO客户端时序图 Java NIO学习笔记 - NIO...

  • java Nio

    NIO编程 网络IO的介绍 nio的概述 通道、 缓冲区、 选择器 网络IO 讲网络IO前,我们先对同步、异步、阻...

  • Netty 源码分析之 番外篇 Java NIO 的前生今世

    简介 Java NIO 是由 Java 1.4 引进的异步 IO.Java NIO 由以下几个核心部分组成: Ch...

  • 第一篇 Java网络编程

    本篇主要从学习角度整理java的几个网络模型,包括: BIO通信模型 伪异步通信模型 NIO通信模型 NIO2.0...

  • 详解IO复用模型select,poll,epoll机制

    在Java中,主要有三种IO模型,分别是阻塞IO(BIO)、非阻塞IO(NIO)和 异步IO(AIO)。Java中...

网友评论

      本文标题:Java NIO学习笔记 - 伪异步IO编程

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