Java学习笔记 -- IO&NIO&AIO学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/l1832876815/article/details/89163039
1. BIO、NIO、AIO的区别?
BIO的特点:面向流、阻塞IO

面向流的IO只能一个字节一个字节读取,通过输入流产生一个字节数据,输出流消费一个字节数据,字节处理速度缓慢。并且在调用read()和write()时线程阻塞,直到有数据被读取或全部数据被写入。阻塞期间不能进行任何其他操作。

NIO的特点:面向缓冲区、非阻塞IO、同步

缓冲区(Buffer): 除boolean外,其余每个基本类型都有其对应的XXBuffer用来存取数据。
通道(Channel): 使用write()和read()方法用来接收和发送缓冲区数据。
选择器(Selector): 通道注册在选择器中,用来管理通道,采用多路复用技术,轮询选择一个当前准备就绪的通道。
以块的形式读取数据,每次产生一个数据块或者消费一个数据块,数据处理速度快。当线程从通道中读取当前数据时,只会读到目前已经有的数据或者读不到数据,写入数据时不需要等到全部写入。期间线程可以完成其他操作,不会阻塞。

AIO的特点:异步、非阻塞

真正实现异步IO请求,将IO请求从应用程序转到操作系统,让操作系统执行IO请求。

2. NIO示例代码
package com.clxk1997;

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;

/**
 * @Description 服务端
 * @Author Clxk
 * @Date 2019/4/9 14:46
 * @Version 1.0
 */
public class NIOServer {

    private Selector selector;
    private ServerSocketChannel serverSocketChannel = null;
    private int keys = 0;


    public void start() throws IOException {
        NIOServer ns = new NIOServer();
        //初始化服务端连接
        ns.initConnect();
        //监听客户端的连接
        ns.listen();
    }

    /**
     * 监听客户端的连接
     */
    private void listen() throws IOException {
        while(true) {
            //让通道管理器至少选择一个通道
            keys = this.selector.select();
            Iterator it = this.selector.selectedKeys().iterator();
            if(keys > 0) {
                while(it.hasNext()) {
                    SelectionKey key = (SelectionKey) it.next();
                    it.remove();
                    //客户端请求连接事件
                    if(key.isAcceptable()) {
                        serverSocketChannel = (ServerSocketChannel) key.channel();
                        //获得和客户端连接的通道
                        SocketChannel socketChannel = serverSocketChannel.accept();
                        socketChannel.configureBlocking(false);
                        socketChannel.write(ByteBuffer.wrap("Hello Client.".getBytes()));
                        socketChannel.register(this.selector,SelectionKey.OP_READ);
                    } else if(key.isReadable()) {
                        read(key);
                    }
                }
            } else {
                System.out.println("Selector finished without any keys.");
            }
        }
    }

    private void read(SelectionKey key) throws IOException {
        SocketChannel socketChannel = (SocketChannel) key.channel();
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        int len = socketChannel.read(byteBuffer);
        String msg = "服务端收到的消息是: " + new String(byteBuffer.array(),0,len);
        System.out.println(msg);
    }

    /**
     * 初始化服务端的连接通道和管理器,已经注册事件
     */
    private void initConnect() throws IOException {
        this.selector = Selector.open();
        serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress("127.0.0.1",8888));
        serverSocketChannel.configureBlocking(false);
        SelectionKey key = serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
        System.out.println("服务端启动成功!");
    }

    public static void main(String[] args) throws IOException {
        new NIOServer().start();
    }
}

package com.clxk1997;

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;

/**
 * @Description 客户端
 * @Author Clxk
 * @Date 2019/4/9 14:46
 * @Version 1.0
 */
public class NIOClient {

    private Selector selector;
    private SocketChannel socketChannel = null;
    private ByteBuffer outBuff = ByteBuffer.allocate(1024);
    private ByteBuffer inBuff = ByteBuffer.allocate(1024);
    private int keys = 0;

    public void start() throws IOException {
        initConnect();
        listen();
    }

    public void listen() throws IOException {
        while(true) {
            keys = this.selector.select();
            if(keys > 0) {
                Iterator it = this.selector.selectedKeys().iterator();
                while(it.hasNext()) {
                    SelectionKey key = (SelectionKey) it.next();
                    if(key.isConnectable()) {
                        SocketChannel sc = (SocketChannel) key.channel();
                        if(sc.isConnectionPending()) {
                            sc.finishConnect();
                            System.out.println("完成连接!");
                        }
                        sc.register(this.selector,SelectionKey.OP_WRITE);
                    } else if(key.isWritable()) {
                        SocketChannel sc = (SocketChannel) key.channel();
                        outBuff.clear();
                        System.out.println("客户端正在写数据...");
                        sc.write(outBuff.wrap("我是ClientA".getBytes()));
                        sc.register(this.selector,SelectionKey.OP_READ);
                        System.out.println("客户端写数据完成!");
                    } else if(key.isReadable()) {
                        SocketChannel sc = (SocketChannel) key.channel();
                        inBuff.clear();
                        System.out.println("客户端正在读数据...");
                        sc.read(inBuff);
                        System.out.println(new String(inBuff.array()));
                        System.out.println("客户端读数据完成!");
                    }
                }
            } else {
                System.out.println("没有找到感兴趣的事件.");
            }
        }
    }

    /**
     * 初始化客户端连接
     * @throws IOException
     */
    public void initConnect() throws IOException {
        selector = Selector.open();
        socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        socketChannel.connect(new InetSocketAddress("127.0.0.1",8888));
        socketChannel.register(this.selector, SelectionKey.OP_CONNECT);
        System.out.println("客户端启动成功!");
    }

    public static void main(String args[]) throws IOException {
        new NIOClient().start();
    }
}

3. AIO示例代码
package com.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.CompletionHandler;
import java.util.concurrent.ExecutionException;

/**
 * @Description 服务端
 * @Author Clxk
 * @Date 2019/4/9 21:19
 * @Version 1.0
 */
public class AIOServer {

    private AsynchronousServerSocketChannel serverSocketChannel = null;

    public AIOServer() throws IOException {
        serverSocketChannel = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(8888));
        serverSocketChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() {
            @Override
            public void completed(AsynchronousSocketChannel result, Void attachment) {
                serverSocketChannel.accept(null,this);
                try {
                    handle(result);
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            @Override
            public void failed(Throwable exc, Void attachment) {
                System.out.println("服务端启动失败!");
            }
        });
    }

    public void handle(AsynchronousSocketChannel result) throws ExecutionException, InterruptedException {
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        result.read(buffer).get();
        buffer.flip();
        System.out.println("服务端接收: " + buffer.get());
    }

    public static void main(String[] args) throws InterruptedException, IOException {
        AIOServer aioServer = new AIOServer();
        System.out.println("服务端开始监听...");
        Thread.sleep(10000);
    }
}

package com.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.AsynchronousSocketChannel;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * @Description 客户端
 * @Author Clxk
 * @Date 2019/4/9 21:26
 * @Version 1.0
 */
public class AIOClient {

    private AsynchronousSocketChannel socketChannel = null;

    public AIOClient() throws IOException, ExecutionException, InterruptedException {
        socketChannel = AsynchronousSocketChannel.open();
        Future<?> future = socketChannel.connect(new InetSocketAddress("127.0.0.1",8888));
        System.out.println(future.get());
    }

    public void write(byte b) {
        ByteBuffer buffer = ByteBuffer.allocate(8);
        buffer.put(b);
        buffer.flip();
        socketChannel.write(buffer);
    }

    public static void main(String[] args) throws InterruptedException, ExecutionException, IOException {
        AIOClient aioClient = new AIOClient();
        aioClient.write((byte) 20);
    }
}

猜你喜欢

转载自blog.csdn.net/l1832876815/article/details/89163039
今日推荐