java IO模型和NIO编程
java IO模型及NIO编程
1.1java支持的网络模型
- BIO(同步阻塞IO)
- NIO(同步非阻塞IO)
- AIO(异步IO)
1.2.阻塞和非阻塞区别
主要指的是访问IO的线程是否会阻塞(或处于等待)
线程访问资源,该资源是否准备就绪的一种处理方式
比如当线程获取资源B之前必须先等待获取资源A,等待A获取完毕后才能进行操作则为阻塞,否则为非阻塞
1.3.同步和异步区别
主要是获取数据的方式,同步异步是等待数据返回,异步异步采用回调,处理完毕通知的方式
1.4.BIO(同步并阻塞IO)
Java BIO就是传统的 socket编程.
BIO(blocking I/O) : 同步阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器
端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,可以通过线程
池机制改善(实现多个客户连接服务器)。
1.4.1.模型图
1.4.2.BIO存在的缺点
- 每个请求都需要创建独立的线程,与对应的客户端进行数据 Read,业务处理,数据 Write
- 并发数较大时,需要创建大量线程来处理连接,系统资源占用较大
- 连接建立后,如果当前线程暂时没有数据可读,则线程就阻塞在 Read 操作上,造成线程资源浪费
1.5. NIO(同步非阻塞)
同步非阻塞,服务器实现模式为一个线程处理多个请求(连接),即客户端发送的连接请求都会注册到
多路复用器上,多路复用器轮询到连接有 I/O 请求就进行处理
1.6 AIO(异步非阻塞)
AIO 引入异步通道的概念,采用了 Proactor 模式,简化了程序编写,有效的请求才启动线程,它的
特点是先由操作系统完成后才通知服务端程序启动线程去处理,一般适用于连接数较多且连接时间较长
的应用
AIO采用异步通知的方式,如事件驱动,当有操作时主动通知服务器。
2.NIO编程
2.1NIO三大核心知识
-
Channel(通道)
-
Buffer(缓存) 面向缓冲区进行编程,可以
-
Selector(选择器)
Java NIO 的非阻塞模式 。使一个线程从某通道发送请求或者读取数据,但是它仅能得到目前可用的
数据,如果目前没有数据可用时,就什么都不会获取,而不是保持线程阻塞,所以直至数据变的可
以读取之前,该线程可以继续做其他的事情。
NIO 的 Selector 、 Channel 和 Buffer 的关系:
-
每个 channel 都会对应一个 Buffer
-
Selector 对应一个线程, 一个线程对应多个 channel(连接)
-
每个 channel 都注册到 Selector选择器上
-
Selector不断轮询查看Channel上的事件, 事件是通道Channel非常重要的概念
-
Selector 会根据不同的事件,完成不同的处理操作
-
Buffer 就是一个内存块 , 底层是有一个数组
-
数据的读取写入是通过 Buffer, 这个和 BIO , BIO 中要么是输入流,或者是输出流, 不能双向,但是 NIO 的 Buffer 是可以读也可以写 , channel 是双向的.
基于NIO服务端的代码实现:
package com.moon.server;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
/**
* @ClassName NIOServer
* @Author zhangqing
* @Date 2022/8/15
* @Description 基于NIO服务端实现
* @Version 1.0
*/
@Slf4j
public class NIOServer {
public NIOServer() {
initService();
}
private void initService() {
try {
//1. 打开一个服务端通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//2. 绑定对应的端口号
int port = 8877;
serverSocketChannel.bind(new InetSocketAddress(port));
//3. 通道默认是阻塞的,需要设置为非阻塞 true(默认) 为通道阻塞 false 为非阻塞
serverSocketChannel.configureBlocking(false);
log.info("NIO服务器启动成功,绑定端口为{}" port);
while (true) {
handle(serverSocketChannel);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void handle(ServerSocketChannel serverSocketChannel) {
// 检查是否有客户端连接 有客户端连接会返回对应的通道 , 否则返回null
try {
SocketChannel socketChannel = serverSocketChannel.accept();
if (socketChannel == null) {
log.info("没有客户端连接");
Thread.sleep(2000);
return;
}
//获取客户端传递过来的数据,并把数据放在byteBuffer这个缓冲区中
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
int read = socketChannel.read(byteBuffer);
log.info("客户端发送的消息为:{}", new String(byteBuffer.array(), 0, read));
socketChannel.write(ByteBuffer.wrap("我是服务端".getBytes(StandardCharsets.UTF_8)));
socketChannel.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
NIOServer nioServer = new NIOServer();
}
}
基于NIO客户端端的代码实现:
package com.moon.client;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.StandardCharsets;
/**
* @ClassName NIOClient
* @Author zhangqing
* @Date 2022/8/15
* @Description Nio客户端
* @Version 1.0
*/
@Slf4j
public class NIOClient {
public static void main(String[] args) {
try {
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("127.0.0.1", 8877));
socketChannel.write(ByteBuffer.wrap("我是客户端 小明".getBytes(StandardCharsets.UTF_8)));
ByteBuffer allocate = ByteBuffer.allocate(1024);
int read = socketChannel.read(allocate);
log.info("服务器返回的数据为{}", new String(allocate.array(),0,read, StandardCharsets.UTF_8));
socketChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
运行效果:
service :
17:26:48.146 [main] INFO com.moon.server.NIOServer - NIO服务器启动成功,绑定端口为{}8877
17:26:48.149 [main] INFO com.moon.server.NIOServer - 没有客户端连接
17:26:50.150 [main] INFO com.moon.server.NIOServer - 没有客户端连接
17:26:52.156 [main] INFO com.moon.server.NIOServer - 客户端发送的消息为:我是客户端 小明
17:26:52.158 [main] INFO com.moon.server.NIOServer - 没有客户端连接
17:26:54.159 [main] INFO com.moon.server.NIOServer - 没有客户端连接
17:26:56.162 [main] INFO com.moon.server.NIOServer - 没有客户端连接
17:26:58.164 [main] INFO com.moon.server.NIOServer - 没有客户端连接
client :
17:26:52.160 [main] INFO com.moon.client.NIOClient - 服务器返回的数据为我是服务端
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhfhfeke
-
第二十二篇Java NIO重点
-
Elasticsearch8 解决启动报错fatal exception while booting Elasticsearchjava.nio.file.InvalidPathException
-
Android 编译jar异常AGPBI: {“kind“:“error“,“text“:“java.nio.file.NoSuchFileException: C:\\Program Files
-
网络通信编程基础,BIO,NIO
-
Java基础:《netty3—NIO:Buffer》
-
java网络和IOBIO/NIO面试题,从Linux底层告诉你为什么Java这么设计----持续补充
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13