🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] # Selector ![](https://img.kancloud.cn/54/ec/54ec00fcc198c888a126544de6d5e9ea_675x408.png) **选择器是NIO的核心,它是channel的管理者** 通过执行select()阻塞方法,监听是否有channel准备好 一旦有数据可读,此方法的返回值是SelectionKey的数量 所以服务端通常会死循环执行select()方法,直到有channl准备就绪,然后开始工作 每个channel都会和Selector绑定一个事件,然后生成一个SelectionKey的对象. 利用Selector可以使一个单独的线程管理多个Channel ~~~ SelectableChannel |-----SocketChannel |-----ServerSocketChannel |-----DatagramChannel ~~~ # 需要注意的是 **channel和Selector绑定时,channel必须是非阻塞模式** **而FileChannel不能切换到非阻塞模式,因为它不是套接字通道,所以FileChannel不能和Selector绑定事件** 在NIO中一共有四种事件: 1. SelectionKey.OP_CONNECT:连接事件 2. SelectionKey.OP_ACCEPT:接收事件 3. SelectionKey.OP_READ:读事件 4. SelectionKey.OP_WRITE:写事件 # 常用方法 ![](https://img.kancloud.cn/21/27/2127187f244fddeb27e52f561c4b49f2_683x303.png) # 代码 ~~~ public class NonBlockingNIOTest { @Test public void client() throws Exception{ InetAddress addr = InetAddress.getByName("127.0.0.1"); SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(addr, 9090)); //设置当前Channel为非阻塞式的 socketChannel.configureBlocking(false); Scanner scanner = new Scanner(System.in); //使用Channel实现数据的读写 ByteBuffer byteBuffer = ByteBuffer.allocate(1024); while(scanner.hasNext()){ String line = scanner.nextLine(); SocketAddress address = socketChannel.getLocalAddress(); byteBuffer.put((address + "-" + new Date() + ":\n" + line).getBytes()); byteBuffer.flip(); socketChannel.write(byteBuffer); byteBuffer.clear(); } socketChannel.close(); } @Test public void server() throws Exception{ ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); //serverSocketChannel设置为非阻塞的 serverSocketChannel.configureBlocking(false); //设置serverSocketChannel的端口号 serverSocketChannel.bind(new InetSocketAddress(9090)); //获取Selector Selector selector = Selector.open(); //注册Selector,表明可以接收客户端的数据 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); SocketChannel socketChannel = null; while(selector.select() > 0){ Iterator<SelectionKey> iterator = selector.selectedKeys().iterator(); while(iterator.hasNext()){ SelectionKey selectionKey = iterator.next(); if(selectionKey.isAcceptable()){//表示当前可以接收客户端数据 //接收到客户端发送来的socketChannel socketChannel = serverSocketChannel.accept(); //设置socketChannel为非阻塞的 socketChannel.configureBlocking(false); //注册 socketChannel.register(selector, SelectionKey.OP_READ); }else if(selectionKey.isReadable()){//表示可以读取客户端的数据 //读取SocketChannel中的数据 socketChannel = (SocketChannel) selectionKey.channel(); ByteBuffer byteBuffer = ByteBuffer.allocate(1024); while(socketChannel.read(byteBuffer) > 0){ byteBuffer.flip(); System.out.println(new String(byteBuffer.array(),0,byteBuffer.limit())); byteBuffer.clear(); } } } iterator.remove(); } socketChannel.close(); serverSocketChannel.close(); selector.close(); } } ~~~