目录
一、阻塞概述
- 一、阻塞概述
- 二、阻塞模式服务端代码示例(使用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
关注打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?