96SEO 2026-02-19 16:32 0
或者面向块编程的。

数据读取到一个它稍后处理的缓冲区需要时可在缓冲区中前后移动这就增加了处理过程中的灵活性使用它可以提供非阻塞式的高伸缩性网络
NIO的非阻塞模式使一个线程从某通道发送请求或者读取数据但是它仅能得到目前可用的数据如果目前没有数据可用时就什么都不会获取而不是保持线程阻塞所以直至数据变的可以读取之前该线程可以继续做其他的事情。
非阻塞写也是如此一个线程请求写入一些数据到某通道但不需要等待它完全写入这个线程同时可以去做别的事情。
通俗理解NIO是可以做到用一个线程来处理多个操作的。
假设有10000个请求过来,根据实际情况可以分配50或者100个线程来处理。
不像之前的阻塞IO那样非得分配10000个。
HTTP2.0使用了多路复用的技术做到同一个连接并发处理多个请求而且并发请求的数量比HTTP1.1大了好几个数量级。
基于Channel(通道)和Buffer(缓冲区)进行操作数据总是从通道读取到缓冲区中或者从缓冲区写入到通道中。
Selector(选择器)用于监听多个通道的事件比如连接请求数据到达等因此使用单个线程就可以监听多个客户端通道
一个线程对应多个channel(连接)该图反应了有三个channel
缓冲区Buffer缓冲区本质上是一个可以读写数据的内存块可以理解成是一个容器对象(含数组)该对象提供了一组方法可以更轻松地使用内存块缓冲区对象内置了一些机制能够跟踪和记录缓冲区的状态变化情况。
Channel
提供从文件、网络读取数据的渠道但是读取或写入的数据都必须经由Buffer
记忆方法:java8大基本类型除了bool类型其他都有buffer对应的子类
ByteBuffer存储字节数据到缓冲区ShortBuffer存储字符串数据到缓冲区CharBuffer存储字符数据到缓冲区IntBuffer存储整数数据到缓冲区LongBuffer存储长整型数据到缓冲区DoubleBuffer存储小数到缓冲区FloatBuffer存储小数到缓冲区
Buffer类定义了所有的缓冲区都具有的四个属性来提供关于其所包含的数据元素的信息:
Capacity:容量即可以容纳的最大数据量在缓冲区创建时被设定并且不能改变Limit:表示缓冲区的当前终点不能对缓冲区超过极限的位置进行读写操作。
且极限是可以修改的Position:
位置下一个要被读或写的元素的索引每次读写缓冲区数据时都会改变改值为下次读写作准备Mark:
hasArray();//告知此缓冲区是否具有可访问的底层实现数组public
arrayOffset();//返回此缓冲区的底层实现数组中第一个缓冲区元素的偏移量public
array)//把一个数组放到缓冲区中使用//构造初始化位置offset和上界length的缓冲区public
);//从当前位置position上getget之后position会自动1public
b);//从当前位置上添加put之后position会自动1public
DatagramChannel、ServerSocketChannel
SocketChannel。
【ServerSocketChanne
transferFrom(ReadableByteChannel
FileChannel(通道)将hello,尚硅谷写入到file01.txt
site.zhourui.nioAndNetty.nio;import
java.nio.channels.FileChannel;public
hello,尚硅谷;//创建一个输出流-channelFileOutputStream
FileOutputStream(d://FileChannel01.txt);//通过
fileOutputStream.getChannel();//创建一个缓冲区
byteBufferbyteBuffer.put(str.getBytes());//对byteBuffer
进行flipbyteBuffer.flip();//将byteBuffer
fileChannelfileChannel.write(byteBuffer);fileOutputStream.close();}
site.zhourui.nioAndNetty.nio;import
java.nio.channels.FileChannel;public
File(d://FileChannel01.txt);FileInputStream
FileInputStream(file);//通过fileInputStream
fileInputStream.getChannel();//创建缓冲区ByteBuffer
通道的数据读入到BufferfileChannel.read(byteBuffer);//将byteBuffer
String(byteBuffer.array()));fileInputStream.close();}
site.zhourui.nioAndNetty.nio;import
java.nio.channels.FileChannel;public
File(d://FileChannel01.txt);FileInputStream
FileInputStream(file);FileChannel
fileInputStream.getChannel();FileOutputStream
File(d://copy.txt));FileChannel
fileOutputStream.getChannel();ByteBuffer
//循环读取//这里有一个重要的操作一定不要忘了/*public
fileChannel.read(byteBuffer);if
(read-1){//表示读完break;}//将buffer
copy.txtbyteBuffer.flip();channel.write(byteBuffer);}//关闭相关的流fileInputStream.close();fileOutputStream.close();}
在每次循环读取数据到byteBuffer之前一定要清空buffer,即byteBuffer.clear();
如果不进行清空buffer,那么5和limit就会一直相等导致read变量后续一直为0,不能跳出循环
site.zhourui.nioAndNetty.nio;import
java.nio.channels.FileChannel;public
FileInputStream(D:\\1.jpeg);FileOutputStream
FileOutputStream(D:\\2.jpeg);//获取各个流对应的filechannelFileChannel
fileInputStream.getChannel();FileChannel
fileOutputStream.getChannel();//使用transferForm完成拷贝
destCh.transferFrom(sourceCh,0,sourceCh.size());sourceCh.transferTo(0,sourceCh.size(),destCh);//关闭相关通道和流sourceCh.close();destCh.close();fileInputStream.close();fileOutputStream.close();}
sourceCh.transferTo(0,sourceCh.size(),destCh);3.3
放入的是什么数据类型get就应该使用相应的数据类型来取出否则可能有
site.zhourui.nioAndNetty.nio;import
java.nio.channels.FileChannel;/*
创建一个随机访问文件流以从具有指定名称的文件中读取并可选择写入。
RandomAccessFile
randomAccessFile.getChannel();/***
DirectByteBuffer*/MappedByteBuffer
channel.map(FileChannel.MapMode.READ_WRITE,
Y);randomAccessFile.close();System.out.println(修改成功~~);}
当channel.map第三个参数为5时mappedByteBuffer.put(5,
‘Y’);会爆IndexOutOfBoundsException
Buffer的分散Scattering和聚集Gathering
site.zhourui.nioAndNetty.nio;import
java.nio.channels.ServerSocketChannel;
java.nio.channels.SocketChannel;
Scattering将数据写入到buffer时可以采用buffer数组依次写入
ServerSocketChannel.open();InetSocketAddress
InetSocketAddress(7000);//绑定端口到socket
并启动serverSocketChannel.socket().bind(inetSocketAddress);//创建buffer数组ByteBuffer[]
ByteBuffer.allocate(5);byteBuffers[1]
ByteBuffer.allocate(3);//等客户端连接(telnet)SocketChannel
serverSocketChannel.accept();int
socketChannel.read(byteBuffers);byteRead
//累计读取的字节数System.out.println(byteRead
limitArrays.asList(byteBuffers).stream().map(buffer
buffer.limit()).forEach(System.out::println);}//将所有的buffer进行flipArrays.asList(byteBuffers).forEach(buffer
buffer.flip());//将数据读出显示到客户端long
socketChannel.write(byteBuffers);
进行clearArrays.asList(byteBuffers).forEach(buffer-
{buffer.clear();});System.out.println(byteRead:
Scattering将数据写入到buffer时可以采用buffer数组依次写入
方式。
可以用一个线程处理多个的客户端连接就会使用到Selector(选择器)Selector
能够检测多个注册的通道上是否有事件发生(注意:多个Channel以事件的方式可以注册到同一个Selector)如果有事件发生便获取事件然后针对每个事件进行相应的处理。
这样就可以只用一个单线程去管理多个通道也就是管理多个连接和请求。
只有在
真正有读写事件发生时才会进行读写就大大地减少了系统开销并且不必为每个连接都创建一个线程不用去维护多个线程避免了多线程之间的上下文切换导致的开销
聚合了Selector(选择器也叫多路复用器)可以同时并发处理成百上千个客户端连接。
当线程从某客户端Socket
通道进行读写数据时若没有数据可用时该线程可以进行其他任务。
线程通常将非阻塞IO
操作所以单独的线程可以管理多个输入和输出通道。
由于读写操作都是非阻塞的这就可以充分提升IO线程的运行效率避免由于频繁I/O阻塞导致的线程挂起。
一个
线程可以并发处理N个客户端连接和读写操作这从根本上解决了传统同步阻塞I/O一连接一线程模型架构的性能、弹性伸缩能力和可靠性都得到了极大的提升。
加入到内部集合中并返回参数timeout用来设置超时时间public
ServerSocketChannel功能类似ServerSocketSocketChannel功能类似Socketselector
selector.select()//阻塞selector.select(1000);//阻塞1000毫秒在1000毫秒后返回selector.wakeup();//唤醒selector
网络编程相关的(Selector、SelectionKey、ServerScoketChannel和SocketChannel)
进行监听select方法,返回有事件发生的通道的个数.将socketChannel注册到Selector上,register(Selector
ops),一个selector上可以注册多个SocketChannel注册后返回一个SelectionKey,会和该Selector
关联(集合)进一步得到各个SelectionKey(有事件发生)在通过SelectionKey反向获取SocketChannel
入门案例实现服务器端和客户端之间的数据简单通讯非阻塞目的理解NIO非阻塞网络编程机制
serverSocketChannel拿到后一定要设置为非阻塞configureBlocking(false)
客户端连接服务器时创建socketChannel之后一定要设置为非阻塞
否则会爆如下异常IllegalBlockingModeException:
我们可以通过key.channel()拿到对应的channel
我们可以通过key.attachment()拿到对应的buffer
OP_READ–读事件OP_WRITE–写事件OP_CONNECT–客户端连接事件OP_ACCEPT–数据接收事件
处理过对应事件的key一定要从selectedKeys中移除,防止重复操作
keyIterator.remove();accept方法是阻塞的,为什么我们serverSocketChannel.accept()程序仍然是非阻塞的?
因为NIO服务端是isAcceptable为true才去accept的,肯定就可以accept成功而BIO则不知道数据什么时候到达accept就会一直阻塞
site.zhourui.nioAndNetty.nio.nioPractise;import
Exception{//创建ServerSocketChannel
ServerSocketServerSocketChannel
ServerSocketChannel.open();//绑定一个端口6666,
在服务器端监听serverSocketChannel.socket().bind(new
InetSocketAddress(8888));//设置为非阻塞serverSocketChannel.configureBlocking(false);//得到一个Selecor对象Selector
OP_ACCEPTserverSocketChannel.register(selector,
SelectionKey.OP_ACCEPT);System.out.println(注册后的selectionkey
(selector.select(1000)0){System.out.println(服务器等待了1秒无连接);continue;}//如果返回的0,
selector.selectedKeys();System.out.println(selectionKeys
selectionKeys.iterator();//监听事件while
(keyIterator.hasNext()){//获取到SelectionKeySelectionKey
对应的通道发生的事件做相应处理if(key.isAcceptable()){//如果是
serverSocketChannel.accept();System.out.println(客户端连接成功
设置为非阻塞socketChannel.configureBlocking(false);//将socketChannel
同时给socketChannel//关联一个BuffersocketChannel.register(selector,SelectionKey.OP_READ,
ByteBuffer.allocate(1024));System.out.println(客户端连接后
key.channel();//获取到该channel关联的bufferByteBuffer
key.attachment();channel.read(buffer);System.out.println(form
String(buffer.array()));}//手动从集合中移动当前的selectionKey,
客户端的socketChannel也一定要设置为非阻塞ByteBuffer.wrap(byte[]
array)方法将字节数组包裹到缓冲区中。
可以获取一个刚好array大小的buffer
site.zhourui.nioAndNetty.nio.nioPractise;import
java.nio.channels.SocketChannel;public
Exception{//得到一个网络通道SocketChannel
SocketChannel.open();//提供服务器端的ip
8888);//设置非阻塞socketChannel.configureBlocking(false);//连接服务器if
(!socketChannel.connect(inetSocketAddress)){while
(!socketChannel.finishConnect()){System.out.println(因为连接需要时间客户端不会阻塞可以做其它工作..);}}//...如果连接成功就发送数据String
buffer//将字节数组包装到缓冲区中。
ByteBuffer
ByteBuffer.wrap(str.getBytes());//发送数据将
channelsocketChannel.write(buffer);System.in.read();}
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback