7. 彤哥说netty系列之Java NIO核心组件之Selector (3)

如果调用wakeup()时并没有线程阻塞在select()上,那么,下一次调用select()将立即返回,不会进入阻塞状态。这跟LockSupport.unpark()方法是比较类似的。

Selector.close()

调用close()方法将会关闭Selector,同时也会将关联的SelectionKey失效,但不会关闭Channel。

举个栗子

nio

public class EchoServer { public static void main(String[] args) throws IOException { // 创建一个Selector Selector selector = Selector.open(); // 创建ServerSocketChannel ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); // 绑定8080端口 serverSocketChannel.bind(new InetSocketAddress(8080)); // 设置为非阻塞模式,本文来源于工从号彤哥读源码 serverSocketChannel.configureBlocking(false); // 将Channel注册到selector上,并注册Accept事件 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); while (true) { // 阻塞在select上 selector.select(); // 如果使用的是select(timeout)或selectNow()需要判断返回值是否大于0 // 有就绪的Channel Set<SelectionKey> selectionKeys = selector.selectedKeys(); // 遍历selectKeys Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { SelectionKey selectionKey = iterator.next(); // 如果是accept事件 if (selectionKey.isAcceptable()) { // 强制转换为ServerSocketChannel ServerSocketChannel ssc = (ServerSocketChannel) selectionKey.channel(); SocketChannel socketChannel = ssc.accept(); System.out.println("accept new conn: " + socketChannel.getRemoteAddress()); socketChannel.configureBlocking(false); // 将SocketChannel注册到Selector上,并注册读事件 socketChannel.register(selector, SelectionKey.OP_READ); } else if (selectionKey.isReadable()) { // 如果是读取事件 // 强制转换为SocketChannel SocketChannel socketChannel = (SocketChannel) selectionKey.channel(); // 创建Buffer用于读取数据 ByteBuffer buffer = ByteBuffer.allocate(1024); // 将数据读入到buffer中 int length = socketChannel.read(buffer); if (length > 0) { buffer.flip(); byte[] bytes = new byte[buffer.remaining()]; // 将数据读入到byte数组中 buffer.get(bytes); // 换行符会跟着消息一起传过来 String content = new String(bytes, "UTF-8").replace("\r\n", ""); if (content.equalsIgnoreCase("quit")) { selectionKey.cancel(); socketChannel.close(); } else { System.out.println("receive msg: " + content); } } } iterator.remove(); } } } } 总结

今天我们学习了Java NIO核心组件Selector,到这里,NIO的三个最重要的核心组件我们就学习完毕了,说实话,NIO这块最重要的还是思维的问题,时刻记着在NIO中一个线程是可以处理多个连接的。

看着Java原生NIO实现网络编程似乎也没什么困难的吗?那么为什么还要有Netty呢?下一章我们将正式进入Netty的学习之中,我们将在其中寻找答案。

最后,也欢迎来我的工从号彤哥读源码系统地学习源码&架构的知识。

nio

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpssgz.html