关于Java你不知道的那些事之NIO使用案例-NIO深入学习

前言【关于Java你不知道的那些事之NIO使用案例-NIO深入学习】本文是基于上一篇文章《关于Java你不知道的那些事之Java NIO(Java程序员的必备技能)》的基础上继续深入学习JavaNIO有关知识 , 如果没有看过上篇文章的同学可以先去看上篇文章 , 回来在看本篇文章 。
关于Java你不知道的那些事之NIO使用案例-NIO深入学习文章插图
BIO概念
在提到NIO之前 , 我们说先看看BIO , 也就是Blocking IO , 阻塞IO , 我们首先实现一个最基本的网络通信 。
/*** QQ客户端** @author: 轻狂书生FS* @create: 2020-09-28-11:09*/ public class QQClient {public static void main(String[] args) throws IOException {Socket socket = new Socket("127.0.0.1", 8080);socket.getOutputStream().write("我来发送".getBytes());} }/*---------------------------------------------------------*/ /*** QQ服务端** @author: 轻狂书生FS* @create: 2020-09-28-11:09*/ public class QQServer {static byte[] bytes = new byte[1024];public static void main(String[] args) throws IOException {while(true) {ServerSocket serverSocket = new ServerSocket();// 绑定IP地址serverSocket.bind(new InetSocketAddress(8080));System.out.println("服务器等待连接....");// 阻塞Socket socket = serverSocket.accept();System.out.println("服务器连接....");// 阻塞System.out.println("等待发送客户端数据");socket.getInputStream().read(bytes);System.out.println("数据接收成功:" + new String(bytes));}} }1234567891011121314151617181920212223242526272829303132333435363738394041424344首先运行Server端 , 然后在运行Client端
服务器等待连接....服务器连接....等待发送客户端数据数据接收成功:我来发送 1234通过运行结果我们能发现 , 服务端线程会进行两次阻塞 , 首先第一次就是在等待连接的时候会阻塞 , 然后是等待数据的时候又会阻塞 。
因此在服务器端 , 不活跃的线程 , 比较多 , 所以我们考虑单线程
BIO怎么改成非阻塞我们从上面的阻塞开始说起
while(true) {ServerSocket serverSocket = new ServerSocket();// 绑定IP地址serverSocket.bind(new InetSocketAddress(8080));// 阻塞Socket socket = serverSocket.accept();// 阻塞socket.getInputStream().read(bytes); }123456789101112假设我们现在访问淘宝网页 , 就相当于我们本机与淘宝的服务器建立了连接 , 然后淘宝服务器就会等待我的请求 , 但是假设我只是打开了网页 , 什么事情都不做 , 如果我的线程被一直阻塞的话 , 那就不能为服务进行接收了 , 这样就会卡在这里 , 但是我也不能为了这个不活跃的用户单独开启线程 , 因为他非常消耗我们的CPU资源 , 这样是会 , 非阻塞IO的用处就来了
在提到NIO之前 , 我们在将刚刚的QQServer改成非阻塞版本的伪代码 , 也就是我们通过一个关键字 , 设置他不阻塞 , 但是因为BIO里面没有这个方法 , 因此他就会一直阻塞着 , 所以把它称为阻塞的
// 设置非阻塞 serverSocket.setConfig();12伪代码如下:
/*** 单线程版服务器 , NIO的伪代码** @author: 轻狂书生FS* @create: 2020-09-28-12:04*/ public class OneThreadServer {public static void main(String[] args) throws IOException {ServerSocket serverSocket = new ServerSocket();serverSocket.bind(new InetSocketAddress(8080));// 套接字列表 , 用于存储List socketList = new ArrayList<>();// 缓冲区byte[] bytes = new byte[1024];// 设置非阻塞 //serverSocket.setConfig();while(true) {// 获取连接Socket socket = serverSocket.accept();// 如果没人连接if(socket == null) {System.out.println("没人连接");// 遍历循环socketList , 套接字listfor(Socket item : socketList) {int read = socket.getInputStream().read(bytes);// 表示有人发送东西if(read != 0) {// 打印出内容System.out.println(new String(bytes));}}} else {// 如果有人连接 , 把套接字放入到列表中socketList.add(socket);// 设置非阻塞 //serverSocket.setConfig();// 遍历循环socketList , 套接字list// 遍历循环socketList , 套接字listfor(Socket item : socketList) {int read = socket.getInputStream().read(bytes);// 表示有人发送东西if(read != 0) {// 打印出内容System.out.println(new String(bytes));}}}}} }12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758


推荐阅读