用缓存器操纵数据:
Buffer由数据和可以高效访问以及操纵这些数据的四个索引组成,这四个索引是:mark、position、limit、capacity。下表是用于设置和复位索引以及查询它们的方法:
capacity() | 返回缓存区容量 |
clear() | 清空缓存区,position=0,limit=capacity,此方法可覆写缓存区 |
flip() | limit=position,position=0,用于准备从缓存区读取已经写入的数据 |
limit() | 返回limit的值 |
limit(int lim) | 设置limit的值 |
mark() | 将mark设置为position |
position() | 返回position的值 |
position(int pos) | 设置position的值 |
remaining() | 返回(limit - position) |
hasRemaining() | 若有介于position和limit之间的元素,返回true |
reset() | 将position设置为mark |
rewind() | 将position设置为0,也就是缓存区的开始位置 |
在缓存区中插入和提取数据的方法会更新这些索引,用于反映所发生的变化。
下面的示例用到一个很简单的算法 - 交换相邻字符,以对CharBuffer中的字符进行编码和译码
public class UsingBuffers { private static void symmetricScramble(CharBuffer buffer) { while (buffer.hasRemaining()) { buffer.mark(); char c1 = buffer.get(); char c2 = buffer.get(); buffer.reset(); buffer.put(c2).put(c1); } } public static void main(String[] args) { char[] data = "UsingBuffers".toCharArray(); ByteBuffer bb = ByteBuffer.allocate(data.length * 2); CharBuffer cb = bb.asCharBuffer(); cb.put(data); print(cb.rewind()); symmetricScramble(cb); print(cb.rewind()); symmetricScramble(cb); print(cb.rewind()); } } /* * Output: UsingBuffers sUniBgfuefsr UsingBuffers */// :~
尽管可以通过对某个char数组调用wrap方法直接产生一个CharBuffer,但是在本例中取而代之的是分配一个底层的ByteBuffer,产生的CharBuffer只是ByteBuffer上的一个视图而已。这里强调的是,我们总是以操纵ByteBuffer为目标,因为只有它才可以和通道进行交互。
刚开始的时候,position指向缓存区第一个元素,capacity和limit指向最后一个元素。
调用get方法和put方法的时候,position指针向前移动1个单位,具体移动几个字节byte,要看数据占用位数大小。
有个重载的get和put方法,带索引参数,不过,这些方法不改变position指针。
mark()方法会在当前位置打个标记,为了以后reset的时候position可以返回这个remark处。
可以直接用带参的put方法去设置相应位置的值,也可以先reset到remark处后,put值。
while循环最后,position指向缓存区的末尾了。如果要打印缓存区,只能打印出position和limit之间的字符,也就是啥都没了。因此这时候要显示缓存区的内容,必须使用rewind()把position设置到缓存区开始位置,这时候mark值变得不明确了。
18.10.6 内存映射文件 - 创建和修改大文件
先看一个瞬间创建一个128M的大文件的例子:
public class LargeMappedFiles { static int length = 0x8FFFFFF; // 128 MB public static void main(String[] args) throws Exception { MappedByteBuffer out = new RandomAccessFile("test.dat", "rw").getChannel() .map(FileChannel.MapMode.READ_WRITE, 0, length); for(int i = 0; i < length; i++) out.put((byte)'x'); print("Finished writing"); for(int i = length/2; i < length/2 + 6; i++) printnb((char)out.get(i)); } } ///:~
为了既能读又能写,我们先由RandomAccessFile开始,获得该文件上的通道,然后调用map()产生MappedByteBuffer,这是一种特殊类型的直接缓存器。我们必须指定映射文件的初始位置和映射区域的长度,这意味着我们可以映射某个大文件的较小的部分。
用这种方式,很大的文件可达2GB也可以很容易的修改。
相比较旧的IO流而言,映射文件访问方式可以大大的提高性能。映射写必须要用RandomAccessFile。
文件加锁:
Java的文件加锁直接映射到了本地操作系统的加锁工具上,因此文件锁对于其他操作系统进程是可见的。
public class FileLocking { public static void main(String[] args) throws Exception { FileOutputStream fos= new FileOutputStream("file.txt"); FileLock fl = fos.getChannel().tryLock(); if(fl != null) { System.out.println("Locked File"); TimeUnit.MILLISECONDS.sleep(100); fl.release(); System.out.println("Released Lock"); } fos.close(); } } /* Output: Locked File Released Lock *///:~
对映射文件的部分加锁:
文件映射通常应用于极大文件,我们可能需要对这种巨大文件进行部分加锁,其他进程可以修改文件中未被加锁的部分。例如数据库文件就是这样。
public class LockingMappedFiles { static final int LENGTH = 0x8FFFFFF; // 128 MB static FileChannel fc; public static void main(String[] args) throws Exception { fc = new RandomAccessFile("test.dat", "rw").getChannel(); MappedByteBuffer out = fc.map(FileChannel.MapMode.READ_WRITE, 0, LENGTH); for(int i = 0; i < LENGTH; i++) out.put((byte)'x'); new LockAndModify(out, 0, 0 + LENGTH/3); new LockAndModify(out, LENGTH/2, LENGTH/2 + LENGTH/4); } private static class LockAndModify extends Thread { private ByteBuffer buff; private int start, end; LockAndModify(ByteBuffer mbb, int start, int end) { this.start = start; this.end = end; mbb.limit(end); mbb.position(start); buff = mbb.slice(); start(); } public void run() { try { // Exclusive lock with no overlap: FileLock fl = fc.lock(start, end, false); System.out.println("Locked: "+ start +" to "+ end); // Perform modification: while(buff.position() < buff.limit() - 1) buff.put((byte)(buff.get() + 1)); fl.release(); System.out.println("Released: "+start+" to "+ end); } catch(IOException e) { throw new RuntimeException(e); } } } }
本人博客已搬家,新地址为:http://yidao620c.github.io/
相关推荐
4. **直接内存访问**:NIO支持直接在物理内存中读写,减少了CPU缓存和主内存之间的数据复制,提高了性能。 **NIO的应用场景:** 1. **高并发网络应用**:如服务器端处理大量客户端连接,NIO的非阻塞和多路复用特性...
### Java NIO 学习笔记 #### 一、概述 Java NIO (Non-Blocking IO,也称为 Java New IO),是 Java 对传统 IO 模型的一次重大改进,旨在提高程序处理大量并发连接的能力。NIO 的核心组件包括 Channels、Buffers 和 ...
- **Buffer**:提供了一种存储和操作数据的高效方式,可以缓存数据,支持各种数据类型,如`ByteBuffer`、`CharBuffer`等。 - **Channel**:作为数据源或目的地,可以从一个通道读取数据到Buffer,或从Buffer写入...
笔记可能包含内存模型、垃圾收集器、JVM诊断工具(如jconsole,jvisualvm)以及性能调优实践。 5. **05消息队列篇.pdf** - 消息队列如RabbitMQ、ActiveMQ或Kafka在分布式系统中扮演着重要角色。笔记可能会讲解消息...
- **缓存机制**:一级缓存(SqlSession级别)和二级缓存(Mapper级别)。 - **MyBatis Plus**:MyBatis的扩展库,提供了更多便利的CRUD操作。 5. **SpringMVC** - **模型绑定**:将表单数据自动绑定到Java对象。...
- 分布式数据库与缓存系统,如MySQL主从复制、Redis缓存。 8. **分布式系统** - CAP理论、BASE理论与分布式一致性。 - 分布式锁、分布式ID生成(如Snowflake算法)、分布式任务调度。 - 分布式服务框架,如...
Java核心面试笔记主要涵盖了一系列深度话题,旨在帮助具备一定编程基础,尤其是工作3-5年的研发人员提升对Java和Spring框架的理解。以下是其中的关键知识点详解: 1. **Java基础**: - **集合与数组**:Java集合...
2. 技能要求降低:Netty抽象了底层的NIO细节,使得开发者不需要深入理解操作系统层面的多路复用IO和Java NIO的复杂性。 3. 高效可靠:Netty提供了心跳机制、断线重连、半包读写等高级特性,增强了网络应用的稳定性和...
- 行为型模式:观察者、模板方法、策略、状态、职责链、命令和迭代器模式。 5. **Spring框架**: - IoC(控制反转)和DI(依赖注入)的概念和实现方式。 - AOP(面向切面编程):切面、通知、目标对象、织入和...
9. **Java**:作为世界上最流行的编程语言之一,Java的学习笔记可能包括基础语法、集合框架、多线程、IO/NIO、异常处理等内容,这些都是Java开发者必备的知识。 10. **数据结构与算法**:这部分是计算机科学的基础...
2. **简化了NIO的使用**:使用Java NIO直接开发需要掌握Java多线程和网络编程等复杂技能,而Netty通过其强大的API和设计模式,降低了开发门槛,使得开发者可以专注于业务逻辑,而不是底层的并发和网络细节。...
### Mina2.0 学习笔记(重点) #### 一、Mina入门 ##### 第一步:下载使用的Jar包 1. **Mina核心库**:登录Mina官网下载`mina2.0.1.zip`,解压后得到`mina-core-2.0.0-M1.jar`。 2. **日志框架SLF4J**:访问SLF4J...
【CoreJava.zip】:核心Java是Java编程的基础,可能包括了Java SE(标准版)中的核心概念和技术,如IO流、NIO(非阻塞I/O)、多线程、并发编程、集合框架的深入探讨、泛型、枚举、Lambda表达式、Stream API等。...
这份名为“Java笔记,从基础到进阶到源码分析,包括但不限于SSM,SpringBoot,SpringCloud,中间件”的压缩包文件,显然是一个全面学习Java技术体系的宝贵资源。我们将详细探讨其中涵盖的关键知识点。 首先,基础...
这份名为“Java最全的架构笔记(共六百多页).zip”的压缩包文件,显然是一个详尽的Java架构学习资源,包含了多个专题系列,旨在帮助开发者深入理解和掌握Java技术栈及其在大规模系统中的应用。以下是根据描述中提到...
- **IO/NIO/BIO**:理解I/O操作的基本概念,对比分析阻塞与非阻塞IO,了解NIO的Channel、Buffer和Selector等核心组件。 2. **设计模式**: - **常用设计模式**:熟悉单例、工厂、代理、装饰器、观察者、适配器、...
3. **改进的集合框架**:在JDK 6中,集合框架得到了进一步增强,包括新增的`LinkedHashMap`的`removeEldestEntry()`方法,用于实现自定义缓存策略,以及`Collections.sort()`和`Arrays.sort()`方法对自定义比较器的...
1. **Java核心技术**:包括Java语法、面向对象编程(OOP)原则、异常处理、多线程、集合框架(如List、Set、Map)、IO流和NIO、反射等基础内容。这些是任何Java开发者必备的基础知识,对于架构师来说更是要精通。 2...
### ActiveMQ 使用笔记 #### 一、ActiveMQ的安装与配置 **1. 安装要求** - **JDK版本**: ActiveMQ要求JDK 1.5或更高版本。为了确保兼容性和稳定性,建议使用较新版本的JDK,例如JDK 1.6或以上。 - **Java环境变量...