Java中BIO、NIO、AIO的原理及其区别

阅读更多
IO的处理方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。
java中IO的主要来源是本地和网络传输。
在了解三种处理方式之前,先了解,同步异步,阻塞非阻塞:
  1、同步: 用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪; 例如自己亲自去       餐厅吃饭
  2、异步:  用户触发IO操作以后,可以干别的事,IO操作完成以后再通知当前线程;例如自己通过美团外卖订购了,送餐上面;自己在等餐到来时间可以干别的事情;
  3、阻塞: 当试图进读写文件的时候,发现不可读取或没东西读,则进入等待状态知道可读;例如去楼下排队等餐;
  4、非阻塞:用户进程访问数据时,会马上返回一个状态值(可读不可读);例如在餐厅吃饭,先取个号,然后坐着等待服务员报号才能入座吃饭(你可以不停的询问服务员还有多久)。(使用非阻塞IO时,如果不能读写Java调用会马上返回,当IO事件分发器会通知可读写时再继续进行读写,不断循环直到读写完成)。
一、同步阻塞BIO
    在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服务端进行通信,默认情况下服务端需要对每个请求建立一堆线程等待请求,而客户端发送请求后,先咨询服务端是否有线程相应,如果没有则会一直等待或者遭到拒绝请求,如果有的话,客户端会线程会等待请求结束后才继续执行。
Java中BIO、NIO、AIO的原理及其区别_第1张图片
该模型最大的问题就是缺乏弹性伸缩能力,当客户端并发访问量增加后,服务端的线程个数和客户端并发访问数呈1:1的正比关系,Java中的线程也是比较宝贵的系统资源,线程数量快速膨胀后,系统的性能将急剧下降,随着访问量的继续增大,系统最终就死掉了。不适合高并发和高性能方面。

二、同步非阻塞的NIO
  NIO详细文档: http://ifeve.com/java-nio-all/
  JDK 1.4中的java.nio.*包中引入新的Java I/O库,其目的是提高速度。实际上,“旧”的I/O包已经使用NIO重新实现过,即使我们不显式的使用NIO编程,也能从中受益。
  NIO我们一般认为是New I/O(也是官方的叫法),因为它是相对于老的I/O类库新增的(其实在JDK 1.4中就已经被引入了,但这个名词还会继续用很久,即使它们在现在看来已经是“旧”的了,所以也提示我们在命名时,需要好好考虑),做了很大的改变。但民间跟多人称之为Non-block I/O,即非阻塞I/O,因为这样叫,更能体现它的特点。而下文中的NIO,不是指整个新的I/O库,而是非阻塞I/O。
    NIO提供了与传统BIO模型中的Socket和ServerSocket相对应的SocketChannel和ServerSocketChannel两种不同的套接字通道实现。
    新增的着两种通道都支持阻塞和非阻塞两种模式。
    阻塞模式使用就像传统中的支持一样,比较简单,但是性能和可靠性都不好;非阻塞模式正好与之相反。
    对于低负载、低并发的应用程序,可以使用同步阻塞I/O来提升开发速率和更好的维护性;对于高负载、高并发的(网络)应用,应使用NIO的非阻塞模式来开发。
服务端流程图:
Java中BIO、NIO、AIO的原理及其区别_第2张图片
客户端流程图:

Java中BIO、NIO、AIO的原理及其区别_第3张图片

客户端代码:
package com.example.demo.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/12
 * Time: 18:15
 * To change this template use File | Settings | File Templates.
 */
public class NioClient implements Runnable{

    private String ip;
    private int port;
    private Selector selector;
    private SocketChannel socketChannel;
    private volatile boolean started;
    public NioClient(String ip,int port){
        this.ip=ip;
        this.port=port;
        try {
            //创建选择器
            selector =Selector.open();
            //打开监听端口
            socketChannel = SocketChannel.open(new InetSocketAddress(ip,port));
            socketChannel.configureBlocking(false);//设置非阻塞模式
            started = true;
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
    public void stop(){
        this.started = false;
    }
    @Override
    public void run() {
        //连接服务器
        try {
            doConnect();
        } catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
        //循环遍历selector  
        while (started) {
            try {
                //无论是否有读写事件发生,selector每隔1s被唤醒一次  
                selector.select(1000);
                //阻塞,只有当至少一个注册的事件发生的时候才会继续.  
//              selector.select();  
                Set keys = selector.selectedKeys();
                Iterator it = keys.iterator();
                SelectionKey key = null;
                while (it.hasNext()) {
                    key = it.next();
                    it.remove();
                    try {
                        handleInput(key);
                    } catch (Exception e) {
                        if (key != null) {
                            key.cancel();
                            if (key.channel() != null) {
                                key.channel().close();
                            }
                        }
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.exit(1);
            }
        }
        //selector关闭后会自动释放里面管理的资源  
        if (selector != null)
            try {
                selector.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
         }

    private void handleInput(SelectionKey key) throws IOException {
        if(key.isValid()){
            SocketChannel sc = (SocketChannel) key.channel();
            if(key.isConnectable()){
                if(sc.finishConnect());
                else System.exit(1);
            }
            //读消息
            if(key.isReadable()){
                //创建ByteBuffer,并开辟一个1M的缓冲区
                ByteBuffer buffer = ByteBuffer.allocate(1024);
                //读取请求码流,返回读取到的字节数
                int readBytes = sc.read(buffer);
                //读取到字节,对字节进行编解码
                if(readBytes>0){
                    //将缓冲区当前的limit设置为position=0,用于后续对缓冲区的读取操作
                    buffer.flip();
                    //根据缓冲区可读字节数创建字节数组
                    byte[] bytes = new byte[buffer.remaining()];
                    //将缓冲区可读字节数组复制到新建的数组中
                    buffer.get(bytes);
                    String result = new String(bytes,"UTF-8");
                    System.out.println("客户端收到消息:" + result);
                }
                //没有读取到字节 忽略
//              else if(readBytes==0);
                //链路已经关闭,释放资源
                else if(readBytes<0){
                    key.cancel();
                    sc.close();
                }
            }
        }
    }

    private void doConnect() throws IOException {
        if(socketChannel.connect(new InetSocketAddress(this.ip,this.port)));
        else socketChannel.register(selector, SelectionKey.OP_CONNECT);
    }
    public void sendMsg(String message) throws IOException {
        socketChannel.register(selector,SelectionKey.OP_READ);
        doWrite(socketChannel,message);
    }
    //异步发送消息
    private void doWrite(SocketChannel channel,String request) throws IOException{
        //将消息编码为字节数组
        byte[] bytes = request.getBytes();
        //根据数组容量创建ByteBuffer
        ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
        //将字节数组复制到缓冲区
        writeBuffer.put(bytes);
        //flip操作
        writeBuffer.flip();
        //发送缓冲区的字节数组
        channel.write(writeBuffer);
        //****此处不含处理“写半包”的代码
    }
}


package com.example.demo.aio;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/13
 * Time: 9:13
 * To change this template use File | Settings | File Templates.
 */
public class RunClient {
    private final static int DEFUALT_PORT=12345;
    private final static String SERVER_IP="127.0.0.1";
    private static NioClient nioClient;

    public static void start(){
        start(DEFUALT_PORT,SERVER_IP);
    }
    public synchronized static void start(int port,String ip){
        if(nioClient!=null)
            nioClient.stop();
        nioClient = new NioClient(ip,port);
        new Thread(nioClient,"client").start();
    }
    //向服务器发送消息
    public static boolean sendMsg(String msg) throws Exception{
        if(msg.equals("q")) return false;
        nioClient.sendMsg(msg);
        return true;
    }
    public static void main(String[] args){
        start();
    }
}


服务端代码:
package com.example.demo.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/12
 * Time: 17:42
 * To change this template use File | Settings | File Templates.
 */
public class NioServer implements Runnable {
    private Selector selector;
    private ServerSocketChannel serverSocketChannel;
    private volatile boolean started;
    public NioServer(int port) throws IOException {
        //指定选择器
        selector = Selector.open();
        //打开监听通道
        serverSocketChannel = ServerSocketChannel.open();
        //设置监听通道是否为阻塞(true)/非阻塞(false)
        serverSocketChannel.configureBlocking(false);   //开启非阻塞模式
        //绑定端口, backlog设为1024
        serverSocketChannel.socket().bind(new InetSocketAddress(port),1024);
        //监听客户端连接请求
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        //标记服务器开启
        started = true;
        System.out.println("AioServer.AioServer已开启端口:"+port);

    }
     public void stop(){
         started =false;
     }
    @Override
    public void run() {
            //如果服务器开启
          while(started){
             //循环变量selector
              try {
                  //无论是否有读写事件发生,selector每隔1s被唤醒一次
                  selector.select(1000);
                  //阻塞,只有当至少一个注册的事件发生的时候才会继续.
//              selector.select();
                  Set set = selector.selectedKeys();
                  Iterator iterator = set.iterator();
                  SelectionKey key = null;
                  while(iterator.hasNext()){
                        key = iterator.next();
                        iterator.remove();;
                      handleInputSelectionKey(key);
                  }
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
    }

    public void handleInputSelectionKey(SelectionKey key) throws IOException {
            if(key.isValid()){
                //处理新接入的请求信息
                if(key.isAcceptable()){
                       ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
                    //通过ServerSocketChannel的accept创建SocketChannel实例
                    //完成该操作意味着完成TCP三次握手,TCP物理链路正式建立
                    SocketChannel sc = ssc.accept();
                    sc.configureBlocking(false);//设置为非阻塞
                    //注册为读
                    sc.register(selector, SelectionKey.OP_READ);
                }
                //读消息
                if(key.isReadable()){
                     SocketChannel sc = (SocketChannel) key.channel();
                    //创建ByteBuffer,并开辟一个1M的缓冲区
                    ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                    ////读取请求码流,返回读取到的字节数
                    int readbytes = sc.read(byteBuffer);
                    //读取到字节,对字节进行编解码
                    if(readbytes >0){
                        //将缓冲区当前的limit设置为position=0,用于后续对缓冲区的读取操作
                        byteBuffer.flip();
                        //根据缓冲区可读字节数创建字节数组
                        byte[] bytes = new byte[byteBuffer.remaining()];
                        //将缓冲区可读字节数组复制到新建的数组中
                        byteBuffer.get(bytes);
                        String msg = new String(bytes,"UTF-8");
                        System.out.println("服务器收到消息:" + msg);
                        //发送应答消息
                        String result = "收到"+msg;
                        doWrite(sc,msg);
                    }
                    //没有读取到字节 忽略
//              else if(readBytes==0);
                    //链路已经关闭,释放资源
                     else if(readbytes<0){
                        key.cancel();
                        sc.close();
                    }

                }
            }
    }
    //异步发送应答消息
    private void doWrite(SocketChannel channel,String response) throws IOException{
        //将消息编码为字节数组
        byte[] bytes = response.getBytes();
        //根据数组容量创建ByteBuffer
        ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
        //将字节数组复制到缓冲区
        writeBuffer.put(bytes);
        //flip操作
        writeBuffer.flip();
        //发送缓冲区的字节数组
        channel.write(writeBuffer);
        //****此处不含处理“写半包”的代码
    }
}


  


package com.example.demo.aio;

import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/12
 * Time: 18:12
 * To change this template use File | Settings | File Templates.
 */
public class RunServer {
    private final  static int PORT = 12345;
    private static NioServer nioServer;
    public static void start(){
        start(PORT);
    }
    public static synchronized void start(int port){
        if(aioServer!=null)
            nioServer.stop();
        try {
            nioServer = new NioServer(port);
        } catch (IOException e) {
            e.printStackTrace();
        }
        new Thread(nioServer,"Server").start();
    }
    public static void main(String[] args){
        start();
    }
}


测试代码:
package com.example.demo.aio;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/13
 * Time: 10:07
 * To change this template use File | Settings | File Templates.
 */
public class NioTest {
    public static void main(String[] args) throws Exception {
        RunServer.start();
        Thread.sleep(1000);
        RunClient.start();
        RunClient.sendMsg("jsjsj");
//        while (RunClient.sendMsg(new Scanner(System.in).nextLine()));
    }
}


三、异步非阻塞AIO
   NIO 2.0引入了新的异步通道的概念,并提供了异步文件通道和异步套接字通道的实现。
    异步的套接字通道时真正的异步非阻塞I/O,对应于UNIX网络编程中的事件驱动I/O(AIO)。他不需要过多的Selector对注册的通道进行轮询即可实现异步读写,从而简化了NIO的编程模型。
  客户端代码:
package com.example.demo.aio;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.CountDownLatch;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/12
 * Time: 18:15
 * To change this template use File | Settings | File Templates.
 */
public class AioClient implements CompletionHandler, Runnable{

    private String ip;
    private int port;
    private AsynchronousSocketChannel asynchronousSocketChannel;
    private CountDownLatch latch;
    public AioClient(String ip,int port){
        this.ip=ip;
        this.port=port;
        try {
            //创建异步的客户端通道
            asynchronousSocketChannel = AsynchronousSocketChannel.open();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public void run() {
        //创建CountDownLatch等待
        latch = new CountDownLatch(1);
        //发起异步连接操作,回调参数就是这个类本身,如果连接成功会回调completed方法
        asynchronousSocketChannel.connect(new InetSocketAddress(ip, port), this, this);
        try {
            latch.await();
        } catch (InterruptedException e1) {
            e1.printStackTrace();
        }
        try {
            asynchronousSocketChannel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //连接服务器成功
    //意味着TCP三次握手完成
    public void completed(Void result, AioClient attachment) {
        System.out.println("客户端成功连接到服务器...");
    }
    //连接服务器失败
    public void failed(Throwable exc, AioClient attachment) {
        System.err.println("连接服务器失败...");
        exc.printStackTrace();
        try {
            asynchronousSocketChannel.close();
            latch.countDown();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //向服务器发送消息
    public void sendMsg(String msg){
        byte[] req = msg.getBytes();
        ByteBuffer writeBuffer = ByteBuffer.allocate(req.length);
        writeBuffer.put(req);
        writeBuffer.flip();
        //异步写
        asynchronousSocketChannel.write(writeBuffer, writeBuffer,new WriteHandler(asynchronousSocketChannel, latch));
    }


}
class WriteHandler implements CompletionHandler {
    private AsynchronousSocketChannel clientChannel;
    private CountDownLatch latch;
    public WriteHandler(AsynchronousSocketChannel clientChannel,CountDownLatch latch) {
        this.clientChannel = clientChannel;
        this.latch = latch;
    }
    public void completed(Integer result, ByteBuffer buffer) {
        //完成全部数据的写入
        if (buffer.hasRemaining()) {
            clientChannel.write(buffer, buffer, this);
        }
        else {
            //读取数据
            ByteBuffer readBuffer = ByteBuffer.allocate(1024);
            clientChannel.read(readBuffer,readBuffer,new ReadClientHandler(clientChannel, latch));
        }
    }
    public void failed(Throwable exc, ByteBuffer attachment) {
        System.err.println("数据发送失败...");
        try {
            clientChannel.close();
            latch.countDown();
        } catch (IOException e) {
        }
    }
}
class ReadClientHandler implements CompletionHandler {
    private AsynchronousSocketChannel clientChannel;
    private CountDownLatch latch;
    public ReadClientHandler(AsynchronousSocketChannel clientChannel,CountDownLatch latch) {
        this.clientChannel = clientChannel;
        this.latch = latch;
    }
    @Override
    public void completed(Integer result,ByteBuffer buffer) {
        buffer.flip();
        byte[] bytes = new byte[buffer.remaining()];
        buffer.get(bytes);
        String body;
        try {
            body = new String(bytes,"UTF-8");
            System.out.println("客户端收到结果:"+ body);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void failed(Throwable exc,ByteBuffer attachment) {
        System.err.println("数据读取失败...");
        try {
            clientChannel.close();
            latch.countDown();
        } catch (IOException e) {
        }
    }
}

package com.example.demo.aio;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/13
 * Time: 9:13
 * To change this template use File | Settings | File Templates.
 */
public class RunClient {
    private final static int DEFUALT_PORT=12345;
    private final static String SERVER_IP="127.0.0.1";
    private static AioClient aioClient;

    public static void start(){
        start(DEFUALT_PORT,SERVER_IP);
    }
    public synchronized static void start(int port,String ip){
        if(aioClient==null){
            aioClient = new AioClient(ip,port);
            new Thread(aioClient,"client").start();
        }
    }
    //向服务器发送消息
    public static boolean sendMsg(String msg) throws Exception{
        if(msg.equals("q")) return false;
        aioClient.sendMsg(msg);
        return true;
    }
    public static void main(String[] args){
        start();
    }
}

服务端代码:
package com.example.demo.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.util.concurrent.CountDownLatch;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/12
 * Time: 17:42
 * To change this template use File | Settings | File Templates.
 */
public class AioServer implements Runnable {
    public CountDownLatch latch;
    public  AsynchronousServerSocketChannel asynchronousServerSocketChannel;
    public AioServer(int port) throws IOException {
        //创建服务通道
        asynchronousServerSocketChannel = AsynchronousServerSocketChannel.open();
        //绑定端口
        asynchronousServerSocketChannel.bind(new InetSocketAddress(port),1024);
        //标记服务器开启
        System.out.println("AioServer.AioServer已开启端口:"+port);

    }
    public void run() {
        //CountDownLatch初始化
        //它的作用:在完成一组正在执行的操作之前,允许当前的现场一直阻塞
        //此处,让现场在此阻塞,防止服务端执行完成后退出
        //也可以使用while(true)+sleep
        //生成环境就不需要担心这个问题,以为服务端是不会退出的
        latch = new CountDownLatch(1);
        //用于接收客户端的连接
        asynchronousServerSocketChannel.accept(this,new AcceptHandler());
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
package com.example.demo.aio;

import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/13
 * Time: 11:35
 * To change this template use File | Settings | File Templates.
 */
//作为handler接收客户端连接
public class AcceptHandler implements CompletionHandler {
    public void completed(AsynchronousSocketChannel channel,AioServer aioServer) {
        //继续接受其他客户端的请求
        RunServer.clientCount++;
        System.out.println("连接的客户端数:" + RunServer.clientCount);
        aioServer.asynchronousServerSocketChannel.accept(aioServer, this);
        //创建新的Buffer
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        //异步读  第三个参数为接收消息回调的业务Handler
        channel.read(buffer, buffer, new ReadHandler(channel));
    }
    public void failed(Throwable exc, AioServer aioServer) {
        exc.printStackTrace();
        aioServer.latch.countDown();
    }
}
package com.example.demo.aio;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/13
 * Time: 11:42
 * To change this template use File | Settings | File Templates.
 */
public class ReadHandler implements CompletionHandler {
    //用于读取半包消息和发送应答
    private AsynchronousSocketChannel channel;
    public ReadHandler(AsynchronousSocketChannel channel) {
        this.channel = channel;
    }
    //读取到消息后的处理
    public void completed(Integer result, ByteBuffer attachment) {
        //flip操作
        attachment.flip();
        //根据
        byte[] message = new byte[attachment.remaining()];
        attachment.get(message);
        try {
            String expression = new String(message, "UTF-8");
            System.out.println("服务器收到消息: " + expression);

            //向客户端发送消息
            doWrite("服务器发送客户端:"+expression);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }
    //发送消息
    private void doWrite(String result) {
        byte[] bytes = result.getBytes();
        ByteBuffer writeBuffer = ByteBuffer.allocate(bytes.length);
        writeBuffer.put(bytes);
        writeBuffer.flip();
        //异步写数据 参数与前面的read一样
        channel.write(writeBuffer, writeBuffer,new CompletionHandler() {
            public void completed(Integer result, ByteBuffer buffer) {
                //如果没有发送完,就继续发送直到完成
                if (buffer.hasRemaining())
                    channel.write(buffer, buffer, this);
                else{
                    //创建新的Buffer
                    ByteBuffer readBuffer = ByteBuffer.allocate(1024);
                    //异步读  第三个参数为接收消息回调的业务Handler
                    channel.read(readBuffer, readBuffer, new ReadHandler(channel));
                }
            }
            public void failed(Throwable exc, ByteBuffer attachment) {
                try {
                    channel.close();
                } catch (IOException e) {
                }
            }
        });
    }
    public void failed(Throwable exc, ByteBuffer attachment) {
        try {
            this.channel.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

package com.example.demo.aio;

import java.io.IOException;

/**
 * Created with IntelliJ IDEA.
 * User: 简德群
 * Date: 2018/3/12
 * Time: 18:12
 * To change this template use File | Settings | File Templates.
 */
public class RunServer {
    private final  static int PORT = 12345;
    private static AioServer aioServer;
    public static int  clientCount =0;
    public static void start(){
        start(PORT);
    }
    public static synchronized void start(int port){
        if(aioServer != null){
            try {
                aioServer = new AioServer(port);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        new Thread(aioServer,"Server").start();
    }
    public static void main(String[] args){
        start();
    }
}


各种I/O的对比:

Java中BIO、NIO、AIO的原理及其区别_第4张图片
BIO、NIO、AIO适用场景分析:

    BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解。

    NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持。

    AIO方式使用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。

另外,I/O属于底层操作,需要操作系统支持,并发也需要操作系统的支持,所以性能方面不同操作系统差异会比较明显。

  • Java中BIO、NIO、AIO的原理及其区别_第5张图片
  • 大小: 25.6 KB
  • Java中BIO、NIO、AIO的原理及其区别_第6张图片
  • 大小: 9.3 KB
  • Java中BIO、NIO、AIO的原理及其区别_第7张图片
  • 大小: 36.8 KB
  • Java中BIO、NIO、AIO的原理及其区别_第8张图片
  • 大小: 44.9 KB
  • 查看图片附件

你可能感兴趣的:(java,IO,NIO,AIO)