[TOC]
## 第一章 緩沖區的使用
在NIO技術的緩沖區中,存在4個核心技術點,分別是:
?capacity(容量)
?limit(限制)
?position(位置)
?mark(標記)

這4個技術點之間值的大小關系如下:0≤mark≤position≤limit≤capacity。
由于ByteBuffer、CharBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer和ShortBuffer是抽象類,wrap()就相當于創建這些緩沖區的工廠方法。最終對應的類型分別為`java.io.HeapByteBuffer`、`java.io.HeapCharBuffer`、`java.io.HeapDoubleBuffe`等。
### limit
限制(limit)代表第一個不應該讀取或寫入元素的index,緩沖區的limit不能為負,并且limit不能大于其capacity。如果position大于新的limit,則將position設置為新的limit。如果mark已定義且大于新的limit,則丟棄該mark。

```java
public class BufferTest {
@Test
public void bufferLimitTest(){
char[] charArray = new char[]{'a','b','c','d','e'};
CharBuffer buffer = CharBuffer.wrap(charArray);
System.out.println("A capacity()=" + buffer.capacity() + ",limit="+buffer.limit());
buffer.limit(3);
System.out.println("B capacity()=" + buffer.capacity() + ",limit="+buffer.limit());
buffer.put(0,'o');
buffer.put(1,'p');
buffer.put(2,'q');
buffer.put(3,'r');//index == 3,第一個不可讀不可寫的索引
buffer.put(4,'s');
buffer.put(5,'t');
buffer.put(6,'u');
}
}
```
### position(位置)
什么是位置呢?它代表“下一個”要讀取或寫入元素的index(索引),緩沖區的position(位置)不能為負,并且position不能大于其limit。如果mark已定義且大于新的position,則丟棄該mark。

```java
@Test
public void bufferLimitTest(){
char[] charArray = new char[]{'a','b','c','d','e'};
CharBuffer buffer = CharBuffer.wrap(charArray);
System.out.println("A capacity()=" + buffer.capacity() + ",limit="+buffer.limit()+ ",position="+buffer.position());
buffer.limit(3);
System.out.println("B capacity()=" + buffer.capacity() + ",limit="+buffer.limit() + ",position="+buffer.position());
buffer.put(0,'o');
buffer.put(1,'p');
buffer.put(2,'q');
buffer.put(3,'r');//index == 3,第一個不可讀不可寫的索引
buffer.put(4,'s');
buffer.put(5,'t');
buffer.put(6,'u');
}
```
> 運行結果如下:
> A capacity()=5,limit=5,position=0
> B capacity()=5,limit=5,position=2
> a
> b
> Z
> d
> e
### mark(標記)
標記有什么作用呢?緩沖區的標記是一個索引,在調用reset()方法時,會將緩沖區的position位置重置為該索引。標記(mark)并不是必需的。定義mark時,不能將其定義為負數,并且不能讓它大于position。
- 如果定義了mark,則在將position或limit調整為小于該mark的值時,該mark被丟棄,丟棄后mark的值是-1。
- 如果未定義mark,那么調用reset()方法將導致拋出`InvalidMarkException`異常。
簡而言之,buffer的reset()方法,可以根據mark()的位置,把位置重置為mark()調用時的位置。
其他的一些關系:
- 如果position大于新的limit,則position的值就是新limit的值。
### 緩沖區操作
| 方法名 | 方法含義 | 用途|
| --- | --- | --- |
| clear() | position=0; limit=capacity; mark = null|還原緩沖區|
| flip() | limit=positon; position=0; | 先寫后讀|
| rewind() | position=0; mark =null| 重讀、重寫|
- clear(),還原緩沖區。還原緩沖區到初始的狀態,包含將位置設置為0,將限制設置為容量,并丟棄標記,即“回到默認”。
- flip()。反轉緩沖區。首先將限制設置為當前位置,然后將位置設置為0。為啥不叫做截取有效緩沖區呢?flip()常用在向緩沖區中寫入一些數據后,下一步讀取緩沖區中的數據之前調用,以改變limit與position的值。
- rewind(),重繞此緩沖區,將位置設置為0并丟棄標記。在重新讀取、重新寫入時可以使用。
## 二、緩沖區的內存分配
### 非直接緩沖區和直接緩沖區
#### 非直接緩沖區

通過ByteBuffer向硬盤存取數據時是需要將數據暫存在JVM的中間緩沖區,如果有頻繁操作數據的情況發生,則在每次操作時都會將數據暫存在JVM的中間緩沖區,再交給ByteBuffer處理,這樣做就大大降低軟件對數據的吞吐量,提高內存占有率,造成軟件運行效率降低,這就是非直接緩沖區保存數據的過程,所以非直接緩沖區的這個弊端就由直接緩沖區解決了。
#### 直接緩沖區

- 前言
- 第一部分 計算機網絡與操作系統
- 大量的 TIME_WAIT 狀態 TCP 連接,對業務有什么影響?怎么處理?
- 性能占用
- 第二部分 Java基礎
- 2-1 JVM
- JVM整體結構
- 方法區
- JVM的生命周期
- 堆對象結構
- 垃圾回收
- 調優案例
- 類加載機制
- 執行引擎
- 類文件結構
- 2-2 多線程
- 線程狀態
- 鎖與阻塞
- 悲觀鎖與樂觀鎖
- 阻塞隊列
- ConcurrentHashMap
- 線程池
- 線程框架
- 徹底搞懂AQS
- 2-3 Spring框架基礎
- Spring注解
- Spring IoC 和 AOP 的理解
- Spring工作原理
- 2-4 集合框架
- 死磕HashMap
- 第三部分 高級編程
- Socket與NIO
- 緩沖區
- Bybuffer
- BIO、NIO、AIO
- Netty的工作原理
- Netty高性能原因
- Rabbitmq
- mq消息可靠性是怎么保障的?
- 認證授權
- 第四部分 數據存儲
- 第1章 mysql篇
- MySQL主從一致性
- Mysql的數據組織方式
- Mysql性能優化
- 數據庫中的樂觀鎖與悲觀鎖
- 深度分頁
- 從一條SQL語句看Mysql的工作流程
- 第2章 Redis
- Redis緩存
- redis key過期策略
- 數據持久化
- 基于Redis分布式鎖的實現
- Redis高可用
- 第3章 Elasticsearch
- 全文查詢為什么快
- battle with mysql
- 第五部分 數據結構與算法
- 常見算法題
- 基于數組實現的一個隊列
- 第六部分 真實面試案例
- 初級開發面試材料
- 答案部分
- 現場編碼
- 第七部分 面試官角度
- 第八部分 計算機基礎
- 第九部分 微服務
- OpenFeign工作原理