Java持久化之 -- 傲娇的NIO
NIO:
Jdk 1.4+ New IO 面向通道和缓冲区
所在包:java.nio
执行流程:
数据总数由通道写入到buffer , 或者是从buffer写入通道

完全替换IO(面向流 单向的)

三个组件:
1. channel 通道
2. Buffer 缓冲区
3. Selector 选择器
NIO和IO 的区别
1. 传统的IO面向流 ,NIO面向缓冲区
2. 传统的IO是阻塞IO ,NIO是非阻塞IO(可并行,,可占位)
3. NOI增加了新功能
① 由选择器
② 可以使用正则表达式
③ 支持内存映射(计算快,效率快)
④ 支持文件锁
一:buffer 缓冲区
读写两种模式
本质上就是一个数据集 数组?集合?
本质是一个可以写入数据,并且从中读取数据的内存!!!
存储的是相同数据类型的数据集
三个重要的值:
1. Position:写入或者读取的数据的当前指针
2. Limit:有多少数据可以写或者可以读
3. Capacity:缓冲区的最大容量
在写(write)模式的情况下
limit 和 capacity 值一致
Position 最大 值{下标(0开始)}是capacity-1
写到哪 值是什么 从0开始
指针的值是 真实值+1 --> 将要写的位置 (最大到capacity值)
xxxBuffer buffer = xxxBuffer.allocate(最大容量);
Buffer.put(xx); 写入数据
在读(read)模式的情况下
Position 读到那值值是几,,但从0开始
Limit 的值是position写模式的值(可读数据)
重设缓冲区 切换到读模式
Buffer.flip();

小Tip:
package com.fsdm.nio.buffer; import java.nio.IntBuffer; /**
* @author 房上的猫
* @create 2018-07-03 17:11
* @博客地址: https://www.cnblogs.com/lsy131479/
* <p>
* NIO 初探缓冲区
**/ public class BufferTest {
public static void main(String[] args) {
//创建缓冲区实例
IntBuffer buffer = IntBuffer.allocate(10);
System.out.println( "\n\n=====================写操作====================\n\n");
//监控各值
System.out.println( "*************** 写模式初始值 ***************");
System.out.println( "capacity=== » " +buffer.capacity());
System.out.println( "position=== » " +buffer.position());
System.out.println( "limit===» "+buffer. limit());
//写入数据
buffer.put(new int[]{1,1,1,2});
//监控各值
System.out.println( "*************** 写入值后 ***************");
System.out.println( "capacity=== » " +buffer.capacity());
System.out.println( "position=== » " +buffer.position());
System.out.println( "limit===» "+buffer. limit());
//重设缓冲区 切换到读模式
buffer.flip();
System.out.println( "\n\n====================读操作=====================\n\n");
//监控各值
System.out.println( "*************** 读模式初始值 ***************");
System.out.println( "capacity=== » " +buffer.capacity());
System.out.println( "position=== » " +buffer.position());
System.out.println( "limit===» "+buffer. limit());
//简单的读操作
while (buffer.hasRemaining()){
System.out.println(buffer.get());
//监控各值
System.out.println( "*************** 读取中 ***************");
System.out.println( "capacity=== » " +buffer.capacity());
System.out.println( "position=== » " +buffer.position());
System.out.println( "limit===» "+buffer. limit());
} }
}
二:channel 管道/通道
作用:
1. 基于buffer(缓冲区)对数据进行读写
2. 管道是双向的,流是单向的
3. 可以异步的读写
常用实现类:
网络传输:
UDP:面向非连接,无脑流,效率高,性能好,非安全
TCP:面向连接,效率低,性能差,安全
1. FileChannel:从文件中读写数据
2. DataGrarmChannel:通过UDP来读写网络中数据
3. SocketChannel:通过TCP读写网络中的数据
4. ServerSocketChannel:可以监听新来的TCP连接,每进来一个,都会创建一个新的 SocketChannel
小Tip:
package com.fsdm.nio.channel; import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channel;
import java.nio.channels.FileChannel; /**
* @author 房上的猫
* @create 2018-07-05 14:09
* @博客地址: https://www.cnblogs.com/lsy131479/
* <p>
* 通过管道向文件中读写数据
**/ public class ChannelDemo {
public static void main(String[] args) {
//准备数据
String[] strs = {"haha","hehe","heihei"};
//写入 文件 输出流
FileOutputStream fos=null;
//准备管道
FileChannel channel = null;
try {
fos = new FileOutputStream("f:/a.txt");
//获取管道数据
channel = fos.getChannel();
//准备缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
//将事先准备好的数据 写入缓冲区
for (String str:strs) {
buffer.put(str.getBytes());
buffer.put("\n".getBytes());
}
//将缓存区切换到读模式
buffer.flip();
//将缓冲区数据读取出来并写入磁盘 真正的写
channel.write(buffer); } catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
//回收资源
try {
channel.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
} }
}
练习实例:(利用管道将a文件内容复制到b文件):
package com.fsdm.nio.channel; import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel; /**
* @author 房上的猫
* @create 2018-07-05 15:02
* @博客地址: https://www.cnblogs.com/lsy131479/
* <p>
* a.txt --> b.txt
**/ public class ChannelBuffer {
public static void main(String[] args) {
//准备起始文件与终止文件
File inFile = new File("f:/a.txt");
File outFile = new File("f:/b.txt");
//准备输入输出流
FileInputStream fis = null;
FileOutputStream fos = null;
//准备双向管道
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
//实例化各对象
fis = new FileInputStream(inFile);
fos = new FileOutputStream(outFile);
inChannel = fis.getChannel();
outChannel = fos.getChannel(); //准备缓存区 (作为中转站)
ByteBuffer buffer = ByteBuffer.allocate(1024);
int num = 0; //写入到缓冲区
while ((num=inChannel.read(buffer))!=-1){
//转换缓冲区模式
buffer.flip();
//读取缓冲区数据并写入到磁盘
outChannel.write(buffer);
//清空缓冲区 方便下次读写
buffer.clear();
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
inChannel.close();
fis.close();
outChannel.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
} }
}
三:selector 选择器
待后期单独总结
高并发:NIO,线程
Java 运行时数据区
运行时都会被创建
共享数据:
堆 heap
方法区 method area
私有数据:
虚拟机栈 vm stack
本地方法栈 native method stack
程序计数器
Xms:初始化容量
Xmx:最大容量
内存映射:
就是把文件映射到电脑中的内存中,通过操作内存从而打到操作文件的目的
内存中操作速度是最快的
Java 中读取文件的几种方式:
1. RandomAceessFile 随机读取,速度最慢
2. FileInputStream 流的方式读取
3. BufferReader 缓存的方式读取
4. MappedByteBuffer 内存映射,速度最快
内存映射的三种模式:MapMode
1. READ_ONLY :对缓冲区的内存只读
2. READ_WRITE :对缓冲区的内存读写
3. PRIVATE :只会对缓冲区的内存进行修改,不会影响到真实的文件
通常适用于数据的读取,一般不会进行对数据的写入
内存映射读取文件与普通读取文件 效率对比:
package com.fsdm.nio; import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel; /**
* @author 房上的猫
* @create 2018-07-05 18:00
* @博客地址: https://www.cnblogs.com/lsy131479/
* <p>
* 内存映射
**/ public class MapperDemo {
public static void main(String[] args) {
FileChannel channel = null;
RandomAccessFile file = null;
try {
file = new RandomAccessFile("e:/struts-2.3.31-lib.zip","rw");
//获取通道
channel = file.getChannel();
//创建内存映射对象
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY,0,channel.size());
byte[] bytes = new byte[1024];
//获取文件大小
long length = file.length();
long begin = System.currentTimeMillis();
ByteBuffer buffer2 = ByteBuffer.allocate(1024);
for (int i=0;i<length;i+=1024){
if (length-i>1024){
buffer2=buffer.get(bytes);
}else{
buffer2=buffer.get(new byte[(int)(length-i)]);
}
buffer2.flip();
buffer2.clear();
}
long end = System.currentTimeMillis();
System.out.println(end-begin);
System.out.println("================");
begin = System.currentTimeMillis();
//普通读取缓冲区
ByteBuffer buffer1 = ByteBuffer.allocate(1024);
while (channel.read(buffer1)!=-1){
buffer1.flip();
buffer.clear();
}
end = System.currentTimeMillis();
System.out.println(end-begin);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
文件锁:
FileLock :基于FlieChannel对文件提供锁的功能
共享锁:
共享读的操作
读可以有多个,但是只能有一个人在写
适合读取数据
目的:是为了防止其他线程拿到独占锁
独占锁:
只能有一个读或写
读写不能同时
适合写数据
Lock():
阻塞
无参默认是独占锁
有参的可设置锁状态
TyLock():
非阻塞
小Tip 玩玩?:
package com.fsdm.nio.lock; import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.OverlappingFileLockException; /**
* @author 房上的猫
* @create 2018-07-05 18:15
* @博客地址: https://www.cnblogs.com/lsy131479/
* <p>
* 锁
**/ public class LockDemo implements Runnable {
static RandomAccessFile file = null;
static FileChannel channel = null;
static FileLock lock = null; public static void main(String[] args) {
Thread thread = null;
try { // lock = channel.lock(0L, Long.MAX_VALUE, true);
} catch (Exception e) {
e.printStackTrace();
}
for (int i = 0; i < 10; i++) {
try {
file = new RandomAccessFile("f:/a.txt", "rw");
channel = file.getChannel();
if (i==0){
lock = channel.lock();
// lock = channel.lock(0L, Long.MAX_VALUE, true);
buffer.put("xx".getBytes()); }
} catch (Exception e) {
e.printStackTrace();
} LockDemo lockDemo = new LockDemo();
thread = new Thread(lockDemo, i+":");
thread.start();
}
try {
System.out.println(Thread.currentThread().getName()+(char)( channel.write(buffer)));
} catch (IOException e) {
e.printStackTrace();
}
;
}
static ByteBuffer buffer = ByteBuffer.allocate(1024);
@Override
public void run() {
try {
buffer =ByteBuffer.allocate(1024);
buffer.put("xx".getBytes());
System.out.println(Thread.currentThread().getName()+(char)( channel.write(buffer)));;
//System.out.println(Thread.currentThread().getName()+(char)( channel.read(buffer)));;
} catch (Exception e){
e.printStackTrace();
} }
}
Java持久化之 -- 傲娇的NIO的更多相关文章
- Java 持久化操作
持久化就是将内存中的数据保存起来,使之可以长期存在. 在Java中 可以做到持久化有很多种方法. 其中有: 1. 堵塞型IO,也就是我们经常说的io流: 2. 非堵塞型IO,通常称为New IO.也就 ...
- JavaEE Tutorials (10) - Java持久化查询语言
10.1查询语言术语14010.2使用Java持久化查询语言创建查询141 10.2.1查询中的命名参数142 10.2.2查询中的位置参数14210.3简化的查询语言语法142 10.3.1选择语句 ...
- 轻量级Java持久化框架,Hibernate完美助手,Minidao 1.6.2版本发布
Minidao 1.6.2 版本发布,轻量级Java持久化框架(Hibernate完美助手) Minidao产生初衷? 采用Hibernate的J2EE项目都有一个痛病,针对复杂业务SQL,hiber ...
- java十分钟速懂知识点——NIO
一.引子 nio是java的IO框架里边十分重要的一部分内容,其最核心的就是提供了非阻塞IO的处理方式,最典型的应用场景就是处理网络连接.很多同学提起nio都能说起一二,但是细究其背后的原理.思想往往 ...
- 京东数科二面:常见的 IO 模型有哪些?Java 中的 BIO、NIO、AIO 有啥区别?
IO 模型这块确实挺难理解的,需要太多计算机底层知识.写这篇文章用了挺久,就非常希望能把我所知道的讲出来吧!希望朋友们能有收货!为了写这篇文章,还翻看了一下<UNIX 网络编程>这本书,太 ...
- 京东数科面试真题:常见的 IO 模型有哪些?Java 中的 BIO、NIO、AIO 有啥区别?
本文节选自<Java面试进阶指北 打造个人的技术竞争力> 面试中经常喜欢问的一个问题,因为通过这个问题,面试官可以顺便了解一下你的操作系统的水平. IO 模型这块确实挺难理解的,需要太多计 ...
- java编解码技术,netty nio
对于java提供的对象输入输出流ObjectInputStream与ObjectOutputStream,可以直接把java对象作为可存储 的字节数组写入文件,也可以传输到网络上去.对与java开放人 ...
- Java IO 之 BIO、NIO、AIO
1.BIO.NIO.AIO解释 Java BIO : 同步并阻塞 (Blocking IO) 一个连接一个线程 即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不 ...
- 漫谈Java IO之 Netty与NIO服务器
前面介绍了基本的网络模型以及IO与NIO,那么有了NIO来开发非阻塞服务器,大家就满足了吗?有了技术支持,就回去追求效率,因此就产生了很多NIO的框架对NIO进行封装--这就是大名鼎鼎的Netty. ...
随机推荐
- 前端常用功能记录(三)—datatables表格初始化
其实上篇说的也算是jQuery Datatables的初始化,但主要是对某些字段意义的理解.下面记录的是datatables常用的功能的初始化. 数据源 我经常使用的有两种,一种是JavaScript ...
- phpstorm 配置 webpack @ 别名跳转
webstorm中专门有webpack的相关配置,默认的路径直接是项目根目录下的 webpack.config.js,但是我们用各种cli生成的项目中,webpack的配置一般都是在build下,导致 ...
- mybatis的面试一对一,一对多,多对多的mapper.xml配置
使用springboot完成一对一,一对多: https://blog.csdn.net/KingBoyWorld/article/details/78966789 传统的mapper文件中的一对一, ...
- linux 系统文件类型、系统安装时间、系统启动时间、系统运行时间、设置及显示时间、系统时间和硬件时间
系统文件类型: 1) $mout 2) df -l:仅列出本地文件系统:-h (--human-readable):-T:文件系统类型 $df -lhf 3) file -s (--special-f ...
- .net 未被引用的错误
开发的时候遇到了一个错误,如下: 错误 1 类型“System.ServiceModel.ClientBase`1<T0>”在未被引用的程序集中定义. 我原本以为是版本号的问题,添加了引用 ...
- influxdb简单使用
之前对influxdb有一个简单的了解和入门的使用,近期由于想使用influxdb做一点东西玩玩,又要捡起influxdb.本篇就针对influxdb的数据库.表的概念,增删改查操作.RESTful操 ...
- weblogic11G 修改密码
weblogic11的登录密码修改方法: 1. 登陆到weblogic后选中domain structure下的security Realms(如图一) (图一) 详情如图二: (图二) 2. 双 ...
- MySql与对应的Java的时间类型
MySql的时间类型有 Java中与之对应的时间类型date java.sql.Date Date ...
- UVALive - 4636 Cubist Artwork(贪心)
题目链接 题意 给出正视图和侧视图,判断最少用几个立方体 分析 若存在高度相同的立方块,则以数目多的那面为准. #include <iostream> #include <cstdi ...
- Splay模板讲解及一些题目
普通平衡树模板以及文艺平衡树模板链接. 简介 平衡二叉树(Balanced Binary Tree)具有以下性质:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二 ...