【读书笔记】Java NIO (中文版) 读书笔记

在这里插入图片描述

概述

这本书讲解的一般吧,主要是讲解了

缓冲区
通道
选择器
正则表达式
字符集

主要是讲解了api的使用,以及部分系统知识,比较底层了,而且大部分都是代码的源码讲解,或者api使用的讲解,太细致了。

学netty之前可以看看这个,或者两者互相弥补。

建议是 如果不用Netty,那么就不要学了,比较底层,看了会忘记。

我是硬着头皮粗略了看了一遍,有空的话,再看第二遍吧。

1.简介

java io 与 系统io的区别

在大多数情况下, Java 应用程序并非真的受着 I/O 的束缚。操作系统并非不能快速传送
数据,让 Java 有事可做;相反,是 JVM 自身在 I/O 方面效率欠佳。操作系统与 Java 基于流的 I/O
模型有些不匹配。操作系统要移动的是大块数据(缓冲区),这往往是在硬件直接存储器存取
(DMA)的协助下完成的。而 JVM 的 I/O 类喜欢操作小块数据——单个字节、几行文本。结果,
操作系统送来整缓冲区的数据, java.io 的流数据类再花大量时间把它们拆成小块,往往拷贝一
个小块就要往返于几层对象。操作系统喜欢整卡车地运来数据, java.io 类则喜欢一铲子一铲子
地加工数据。有了 NIO,就可以轻松地把一卡车数据备份到您能直接使用的地方( ByteBuffer 对
象)。

只要坚持使用基于数组的 read( )和 write( )方法。这些方法与底层操作系统调用相当接近,尽管必须保留至少一份缓冲区拷贝。

缓冲区,以及缓冲区如何工作,是所有 I/O 的基础。所谓“输入/输出”讲的无非就是把数据移进或移出缓冲区。

I/O 缓冲区操作简图

扫描二维码关注公众号,回复: 12738157 查看本文章

在这里插入图片描述

三个缓冲区的发散读操作

在这里插入图片描述

内存空间多重映射

在这里插入图片描述

前提条件是,内核与用户缓冲区必须使用相同的页对齐,缓冲区的大小还必须是磁盘控制器块大小(通常为 512 字节磁盘扇区)的倍数。操作系统把内存地址空间划分为页,即固定大小的字节组。内存页的大小总是磁盘块大小的倍数,通常为 2 次幂(这样可简化寻址操作)。

页错误随即产生一个陷阱(类似于系统调用),把控制权移交给内核,附带导致错误的虚拟地址信息,然后内核采取步骤验证页的有效性。

1.4.1 文件IO

  1. 磁盘属硬件设备,对何谓文件一无所知.
  2. 文件系统是更高层次的抽象,是安排、解释磁盘(或其他随机存取块设备)数据的一种独特方式。

用户内存到文件系统页的映射

在这里插入图片描述

文件锁定

  1. 文件锁定机制允许一个进程阻止其他进程存取某文件,或限制其存取方式。通常的用途是控制共享信息的更新方式,或用于事务隔离。在控制多个实体并行访问共同资源方面,文件锁定是必不可少的。数据库等复杂应用严重信赖于文件锁定

文件锁定有两种方式:共享的和独占的。多个共享锁可同时对同一文件区域发生作用;独占锁则不同,它要求相关区域不能有其他锁定在起作用。

2.缓冲区

  1. 缓冲区是包在一个对象内的基本数据元素数组。

2.1 属性

所有的缓冲区都具有四个属性来提供关于其所包含的数据元素的信息。它们是:

容量(Capacity)

缓冲区能够容纳的数据元素的最大数量。这一容量在缓冲区创建时被设定,并且永远不能被改变。

上界(Limit)

缓冲区的第一个不能被读或写的元素。或者说,缓冲区中现存元素的计数。

位置(Position)

下一个要被读或写的元素的索引。位置会自动由相应的 get( )和 put( )函数更新。

标记(Mark)

一个备忘位置。调用 mark( )来设定 mark = postion。调用 reset( )设定 position =mark。标记在设定前是未定义的(undefined)。

这四个属性之间总是遵循以下关系:

0 <= mark <= position <= limit <= capacity

在这里插入图片描述

这一章主要介绍各种buffer。

2.2 flip

Flip()函数将一个能够继续添加数据元素的填充状态的缓冲区翻转成一个准备读出元素的释放状态。

类似于下面的代码

buffer.limit(buffer.position()).position(0);

2.3 clear

Clear()函数将缓冲区重置为空状态。 它并不改变缓冲区中的任何数据元素,而是仅仅将上界设为容量的值,并把位置设回 0。

2.4 mark

标记,使缓冲区能够记住一个位置并在之后将其返回。缓冲区的标记在 mark( )函数被调用之前是未定义的,调用时标记被设为当前位置的值。 reset( )函数将位置设为当前的标记值。如果标记值未定义,调用 reset( )将导致 InvalidMarkException 异常。一些缓冲区函数会抛弃已经设定的标记( rewind( ), clear( ),以及 flip( )总是抛弃标记)。如果新设定的值比当前的标记小,调用limit( )或 position( )带有索引参数的版本会抛弃标记.

2.5 比较

两个缓冲区被认为相等的充要条件是:32

  1. 两个对象类型相同。包含不同数据类型的 buffer 永远不会相等,而且 buffer绝不会等于非 buffer 对象。
  2. 两个对象都剩余同样数量的元素。 Buffer 的容量不需要相同,而且缓冲区中剩余数据的索引也不必相同。但每个缓冲区中剩余元素的数目(从位置到上界)必须相同。
  3. 在每个缓冲区中应被 Get()函数返回的剩余数据元素序列必须一致。

两个被认为是相等的缓冲区

在这里插入图片描述

两个被认为不相等的缓冲区

在这里插入图片描述

3.6 字节顺序

大端字节顺序

在这里插入图片描述

小端字节顺序
在这里插入图片描述

多字节数值被存储在内存中的方式一般被称为 endian-ness(字节顺序)。如果数字数值的最高字节——big end(大端),位于低位地址,那么系统就是大端字节顺序。如果最低字节最先保存在内存中,那么小端字节顺序。

ByteOrder 类定义了决定从缓冲区中存储或检索多字节数值时使用哪一字节顺序的常量。

ByteBuffer 类有所不同:默认字节顺序总是 ByteBuffer.BIG_ENDIAN,无论系统的固有字节顺序是什么。 Java 的默认字节顺序是大端字节顺序。

3.6.1 直接缓冲区

3.通道

4.选择器

5.正则表达式

6.字符集

猜你喜欢

转载自blog.csdn.net/qq_21383435/article/details/114898456