介绍

JAVA NIO 支持面向缓冲区的,基于通道的IO操作,NIO将以更加高效的方式进行文件的读写操作

阻塞IO

一个请求对应一个线程,代码会阻塞直至有可供读取的数据

非阻塞IO NIO

采取了基于Reactor模式的工作方式,I/O调用不会被阻塞
核心对象是selector
本质是延迟IO操作

三个核心部分

  • channels

双向 (steam单向)

  • buffers
  • selectors

channel概述

通道 通过它读取和写入操作 双向 全双工
在字节缓冲区和位于通道另一侧的实体有效的传输数据
image.png

FileChannel

打开filechannel RandomAcessFile出啊关键
读取数据
写入数据

position方法

transferTo

transferFrom

通道之间的数据传输

Socket通道

运行非阻塞模式
一个或几个线程就可以管理成百上千的活动socket

ServerSocketChannel

  1. public static void main(String[] args) throws IOException, InterruptedException {
  2. //端口号
  3. int port = 8888;
  4. //buffer
  5. ByteBuffer buffer = ByteBuffer.wrap("hello atguigu".getBytes());
  6. ServerSocketChannel ssc = ServerSocketChannel.open();
  7. //绑定
  8. ssc.socket().bind(new InetSocketAddress(port));
  9. //设置非阻塞模式
  10. ssc.configureBlocking(false);
  11. while (true){
  12. SocketChannel sc = ssc.accept();
  13. if (sc == null){
  14. System.out.println("null");
  15. Thread.sleep(2000);
  16. }else {
  17. System.out.println("链接来自于"+sc.socket().getRemoteSocketAddress());
  18. buffer.rewind();//指针0
  19. sc.write(buffer);
  20. sc.close();
  21. }
  22. }
  23. }

DatagramChannel

关联的DatagramSocket对象
UDP 模拟包导向
发送单独的数据包给不同的目的地址

SocketChannel

连接到TCP网络套接字的通道

  • 创建SocketChannel ```markdown public class SocketChannelDemo { public static void main(String[] args) throws Exception {
    1. //创建
    2. SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("www.baidu.com",80));
    3. //连接检验
    4. //设置阻塞模式和非阻塞模式
    5. socketChannel.configureBlocking(false);
    6. //读写面向缓冲区
    } }

```

Scatter/gather

Buffer

与NIO通道进行交互
所有的数据都是用缓冲区处理的
缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存
NIO中所有的缓冲区类型都继承抽象类Buffer
buffer读写数据的四个步骤

  • 写入数据到buffer
  • 调用flip()方法
  • 从buffer中读取数据
  • 调用clear()方法或者compact()方法

    三个属性和类型

  • capacity

  • position
    • 读模式

读入数据的当前位置

  • 写模式

当前插入位置

  • limit
    • write

最多可以写入多少数据 ==capacity

  • read

表示有多少个可读数据

分配和读写数据

  • buffer分配

allocate()方法

  • 写数据

channel写入 read()
put()方法

  • flip()方法

从写的模式变成读的模式
将position=0
limit =position

读取数据

write()
get()

几个方法

  • rewind()方法
  • clear()与compact()
  • mark()和reset()

    缓冲区操作

    缓冲区分片

    从现有缓冲区上切出一片来作为新的缓冲区,底层数组层面上数据共享
    slice()方法

    只读缓冲区

    asReadOnlyBuffer()将任何缓冲区转换为只读缓冲区

    直接缓冲区

    allocateDirect()方法
    尽最大努力直接对他执行本机I/O操作

内存映射文件I/O

Selector

选择器 多路复用器 检查channel的状态是否处于可读,可写
单线程管理多个channels
使用更少的线程来处理通道,避免上下文切换带来的消耗。

可选择通道

SelectableChannel

channel注册到selector

channel.register(Selector sel,int ops)方法
sel 通道要注册的选择器
ops 要查询的通道操作

编程步骤总结

image.png

Pipe

管道 2个线程之间的单向数据连接,有一个source通道和一个sink通道
数据会被写道sink通道,从source通道读取

FileLock

文件锁

  • 排它锁
  • 共享锁

lock和trylock

  • lock 阻塞
  • tryLock 非阻塞

    path

files

java nio完成一个多人聊天室功能