首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Java 17 - NIO

Java 17 - NIO

作者头像
Reck Zhang
发布2021-08-11 12:18:17
发布2021-08-11 12:18:17
4630
举报
文章被收录于专栏:Reck ZhangReck Zhang

NIO

概念

我们传统上处理socket IO时, 需要给每一个连接创建一个线程, 当并发的连接数量非常大的时候, 线程所占用的栈内存和CPU线程切换的开销将非常大. 如果使用NIO, 那么不需要为每一个连接创建一个单独的线程, 可以用一个含有有限数量线程的线程池, 甚至是一个线程来为任意数量的连接提供服务. 由于线程数量小于连接数量, 那么就决定了IO的工作模式不能是阻塞, 否则有些连接就会被饿死.

原理

  1. 由一个专门的线程来处理所有的IO事件, 并负责转发.
  2. 事件驱动机制: 事件到的时候触发, 而不是同步的去监视事件.
  3. 线程通讯: 线程之间通过wait, notify等方式通讯, 保证每次上下文切换是有意义的, 减少无畏的线程切换.

NIO实现了IO多路复用中的Reactor模型, 一个线程使用Selector通过轮询的方式去监听多个Channel上的时间, 从而使一个线程可以处理多个事件.

注意的是, 只有为SocketChannel才能配置非阻塞, 而为FileChannel不能, 况且这也没有意义.

注册Channel

当我们将Channel注册到Selector上时, 要指定注册的具体事件, 事件的定义如下:

代码语言:javascript
复制
public static final int OP_READ = 1 << 0;
public static final int OP_WRITE = 1 << 2;
public static final int OP_CONNECT = 1 << 3;
public static final int OP_ACCEPT = 1 << 4;

我们将事件状态压缩, 这样可以通过|来表示多个事件类型.

优点

总的来说, NIO对比BIO有如下优点:

  1. 节约了大量线程所占用的栈空间.
  2. 避免线程之间的切换所带来的花费.
  3. 数据块为单位的IO速度高于传统的流式读取速度.

实例

代码语言:javascript
复制
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
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;

class NIOServer {
    private static String readDataFromSocketChannel(SocketChannel socketChannel) throws IOException {
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
        StringBuilder data = new StringBuilder();
        while(true) {
            byteBuffer.clear();
            int n = socketChannel.read(byteBuffer);
            if(n == -1) {
                break;
            }
            byteBuffer.flip();
            int limit = byteBuffer.limit();
            char[] currentData = new char[limit];
            for(int i = 0; i < limit; i++) {
                currentData[i] = (char) byteBuffer.get(i);
            }
            data.append(currentData);
        }
        return data.toString();
    }

    public static void main(String[] args) throws IOException {
        Selector selector = Selector.open();

        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        ServerSocket serverSocket = serverSocketChannel.socket();
        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 8888);
        serverSocket.bind(inetSocketAddress);

        while(true) {
            selector.select();
            Set<SelectionKey> keys = selector.selectedKeys();
            Iterator<SelectionKey> keyIterator = keys.iterator();
            while(keyIterator.hasNext()) {
                SelectionKey selectionKey = keyIterator.next();
                if(selectionKey.isAcceptable()) {
                    ServerSocketChannel serverSocketChannel1 = (ServerSocketChannel) selectionKey.channel();
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if(selectionKey.isReadable()) {
                    SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
                    System.out.println(readDataFromSocketChannel(socketChannel));
                    socketChannel.close();
                }
                keyIterator.remove();
            }
        }
    }
}

class NIOClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 8888);
        OutputStream outputStream = socket.getOutputStream();
        String string = "Hello World!";
        outputStream.write(string.getBytes());
        outputStream.close();
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-07-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • NIO
    • 概念
    • 原理
    • 注册Channel
    • 优点
    • 实例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档