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. ...
随机推荐
- D. Recovering BST Codeforces Round #505 (rated, Div. 1 + Div. 2, based on VK Cup 2018 Final)
http://codeforces.com/contest/1025/problem/D 树 dp 优化 f[x][y][0]=f[x][z][1] & f[z+1][y][0] ( gcd( ...
- Linux掉电处理
在嵌入式设备中,掉电处理一直是一项比较麻烦的工作,在具有Linux系统的设备中,系统的种种数据的处理更是增加掉电处理的难度.现在做以下几点总结,再遇到类似问题可以做个参考. 1,系统启动的处理 在系统 ...
- SQL Server - 开窗函数
-- 开窗函数:在结果集的基础上进一步处理(聚合操作) SELECT * FROM dbo.Student S# Sname Sage Ssex ---------- ---------- ----- ...
- angularJs的各种服务和指令的使用场景
$location服务,获取页面跳转带的参数 比如说页面是这样的 localhost:9102/admin/goods.html#?id=123 如何获取这个id=123的值呢?????(注意: ...
- 【1】ConcurrentModificationException 异常解析和快速失败,安全失败
目录 一.引起异常的代码 二.foreach原理 三.从ArrayList源码找原因 四.单线程解决方案 五.在多线程环境下的解决方法 一.引起异常的代码 以下三种的遍历集合对象时候,执行集合的rem ...
- 浅谈 JSON 那些被转义的字符们
其实,之前我一直以为 JSON 会把 ASCII 可显示字符以外的统统转义为 Unicode,直到有一次我用 JSON.stringify 才发现,其实是 PHP 为我们想的太周到了. 我以前是一位 ...
- 为ASP.NET控件加入快捷菜单
ContextMenu Control 快捷菜单控件概述: MSDN Liabrary 中包含了几个DHTML快捷菜单的示例.分别提供了对这一功能的不能实现方法.一个快捷菜单就是在页面中任何位置的一组 ...
- shell 判断脚本参数
测试登陆脚本 ./test.sh -p 123 -P 3306 -h 127.0.0.1 -u root #!/bin/sh ];then echo "USAGE: $0 -u user - ...
- HDU 1262 寻找素数对 模拟题
题目描述:输入一个偶数,判断这个偶数可以由哪两个差值最小的素数相加,输出这两个素数. 题目分析:模拟题,注意的是为了提高效率,在逐个进行判断时,只要从2判断到n/2就可以了,并且最好用打表法判断素数. ...
- CentOS7 关闭防火墙和selinux
本文将简单介绍在CentOS7上如何临时和永久关闭防火墙和selinux. 关闭防火墙 # 查看防火墙状态 [root@localhost ~]# systemctl status firewalld ...