目录
一、阻塞概述
- 一、阻塞概述
- 二、阻塞模式服务端代码示例(使用nio实现)
- 三、阻塞模式客户端代码示例(使用nio实现)
- 四、工具类代码示例
- 五、阻塞模式代码示例本地调试
- 阻塞模式下,相关方法都会导致线程暂停。 (1)、ServerSocketChannel.accept 会在没有连接建立时让线程暂停; (2)、SocketChannel.read 会在没有数据可读时让线程暂停; (3)、阻塞的表现其实就是线程暂停了,暂停期间不会占用 cpu,但线程相当于闲置;
- 单线程下,阻塞方法之间相互影响,几乎不能正常工作,需要多线程支持。
- 但多线程下,有新的问题,体现在以下方面 (1)、32 位 jvm 一个线程 320k,64 位 jvm 一个线程 1024k,如果连接数过多,必然导致 OOM,并且线程太多,反而会因为频繁上下文切换导致性能降低; (2)、可以采用线程池技术来减少线程数和线程上下文切换,但治标不治本,如果有很多连接建立,但长时间 inactive,会阻塞线程池中所有线程,因此不适合长连接,只适合短连接;
-
服务端代码
package com.example.nettytest.nio.day3; import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.*; import java.util.ArrayList; import java.util.Iterator; import static com.example.nettytest.nio.day1.ByteBufferUtil.debugRead; /** * @description: 阻塞模式服务端代码示例(使用nio实现) * @author: xz * @create: 2022-08-15 21:21 */ @Slf4j public class TestServer { public static void main(String[] args) throws IOException { nioBlockServer(); } /** * 使用nio来理解阻塞模式(单线程服务端) * */ private static void nioBlockServer() throws IOException { //1、创建ByteBuffer,容量16 ByteBuffer byteBuffer = ByteBuffer.allocate(16); //2、创建服务器 ServerSocketChannel ssc = ServerSocketChannel.open(); //3、绑定监听端口 ssc.bind(new InetSocketAddress(8080)); //4、连接集合 ArrayList channels = new ArrayList(); while(true){ log.info("connecting..."); //5、accept() 建立与客户端连接, SocketChannel 用来与客户端之间通信 SocketChannel sc = ssc.accept();//启动服务端,阻塞方法,线程停止运行 log.info("create connected SocketChannel... {}", sc); //6、建立的客户端连接sc 添加到 连接集合channels中 channels.add(sc); //7、遍历连接集合 for(SocketChannel channel : channels){ log.info("before read channel ... {}", channel); // 8、 接收客户端发送的数据,从channel中读取数据写入到byteBuffer中 channel.read(byteBuffer);// 启动客户端,阻塞方法,线程停止运行 //切换读模式 byteBuffer.flip(); //打印可读取内容(从byteBuffer中读取数据内容) debugRead(byteBuffer); //切换回写模式 byteBuffer.clear(); log.info("after read channel ... {}", channel); } } } }
-
客户端代码
package com.example.nettytest.nio.day3; import java.io.IOException; import java.net.InetSocketAddress; import java.net.SocketAddress; import java.nio.channels.SocketChannel; /** * @description: * @author: xz * @create: 2022-08-15 21:45 */ public class TestClient { public static void main(String[] args) throws IOException { SocketChannel sc = SocketChannel.open(); sc.connect(new InetSocketAddress("localhost", 8080)); SocketAddress address = sc.getLocalAddress(); //debug模式后,点击src参数,右键选择 输入表达式sc.write(Charset.defaultCharset().encode("hello"));然后执行 System.out.println("waiting..."); } }
- 工具类,打印输入、输出数据使用
package com.example.nettytest.nio.day1; import io.netty.util.internal.StringUtil; import java.nio.ByteBuffer; import static io.netty.util.internal.MathUtil.isOutOfBounds; import static io.netty.util.internal.StringUtil.NEWLINE; public class ByteBufferUtil { private static final char[] BYTE2CHAR = new char[256]; private static final char[] HEXDUMP_TABLE = new char[256 * 4]; private static final String[] HEXPADDING = new String[16]; private static final String[] HEXDUMP_ROWPREFIXES = new String[65536 >>> 4]; private static final String[] BYTE2HEX = new String[256]; private static final String[] BYTEPADDING = new String[16]; static { final char[] DIGITS = "0123456789abcdef".toCharArray(); for (int i = 0; i 4 & 0x0F]; HEXDUMP_TABLE[(i
关注打赏
热门博文
- Netty——网络编程 NIO(Selector处理accept事件)代码示例
- CompletableFuture异步编排(多任务组合)
- CompletableFuture异步编排(线程串行化代码示例)
- CompletableFuture异步编排(handle最终处理)
- CompletableFuture异步编排(计算完成回调代码示例)
- hutool工具导出excel代码示例
- java 获取音频、视频文件时长代码示例
- PostMan发送请求参数带有路径特殊字符会返回400错误(与URL字符及URL编码值有关)
- Rabbitmq与Erlang安装包下载图解
- idea2021.1版本SpringBoot项目日志的说明及使用