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的更多相关文章

  1. Java 持久化操作

    持久化就是将内存中的数据保存起来,使之可以长期存在. 在Java中 可以做到持久化有很多种方法. 其中有: 1. 堵塞型IO,也就是我们经常说的io流: 2. 非堵塞型IO,通常称为New IO.也就 ...

  2. JavaEE Tutorials (10) - Java持久化查询语言

    10.1查询语言术语14010.2使用Java持久化查询语言创建查询141 10.2.1查询中的命名参数142 10.2.2查询中的位置参数14210.3简化的查询语言语法142 10.3.1选择语句 ...

  3. 轻量级Java持久化框架,Hibernate完美助手,Minidao 1.6.2版本发布

    Minidao 1.6.2 版本发布,轻量级Java持久化框架(Hibernate完美助手) Minidao产生初衷? 采用Hibernate的J2EE项目都有一个痛病,针对复杂业务SQL,hiber ...

  4. java十分钟速懂知识点——NIO

    一.引子 nio是java的IO框架里边十分重要的一部分内容,其最核心的就是提供了非阻塞IO的处理方式,最典型的应用场景就是处理网络连接.很多同学提起nio都能说起一二,但是细究其背后的原理.思想往往 ...

  5. 京东数科二面:常见的 IO 模型有哪些?Java 中的 BIO、NIO、AIO 有啥区别?

    IO 模型这块确实挺难理解的,需要太多计算机底层知识.写这篇文章用了挺久,就非常希望能把我所知道的讲出来吧!希望朋友们能有收货!为了写这篇文章,还翻看了一下<UNIX 网络编程>这本书,太 ...

  6. 京东数科面试真题:常见的 IO 模型有哪些?Java 中的 BIO、NIO、AIO 有啥区别?

    本文节选自<Java面试进阶指北 打造个人的技术竞争力> 面试中经常喜欢问的一个问题,因为通过这个问题,面试官可以顺便了解一下你的操作系统的水平. IO 模型这块确实挺难理解的,需要太多计 ...

  7. java编解码技术,netty nio

    对于java提供的对象输入输出流ObjectInputStream与ObjectOutputStream,可以直接把java对象作为可存储 的字节数组写入文件,也可以传输到网络上去.对与java开放人 ...

  8. Java IO 之 BIO、NIO、AIO

    1.BIO.NIO.AIO解释 Java BIO : 同步并阻塞 (Blocking IO) 一个连接一个线程 即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不 ...

  9. 漫谈Java IO之 Netty与NIO服务器

    前面介绍了基本的网络模型以及IO与NIO,那么有了NIO来开发非阻塞服务器,大家就满足了吗?有了技术支持,就回去追求效率,因此就产生了很多NIO的框架对NIO进行封装--这就是大名鼎鼎的Netty. ...

随机推荐

  1. 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( ...

  2. Linux掉电处理

    在嵌入式设备中,掉电处理一直是一项比较麻烦的工作,在具有Linux系统的设备中,系统的种种数据的处理更是增加掉电处理的难度.现在做以下几点总结,再遇到类似问题可以做个参考. 1,系统启动的处理 在系统 ...

  3. SQL Server - 开窗函数

    -- 开窗函数:在结果集的基础上进一步处理(聚合操作) SELECT * FROM dbo.Student S# Sname Sage Ssex ---------- ---------- ----- ...

  4. angularJs的各种服务和指令的使用场景

    $location服务,获取页面跳转带的参数 比如说页面是这样的  localhost:9102/admin/goods.html#?id=123   如何获取这个id=123的值呢?????(注意: ...

  5. 【1】ConcurrentModificationException 异常解析和快速失败,安全失败

    目录 一.引起异常的代码 二.foreach原理 三.从ArrayList源码找原因 四.单线程解决方案 五.在多线程环境下的解决方法 一.引起异常的代码 以下三种的遍历集合对象时候,执行集合的rem ...

  6. 浅谈 JSON 那些被转义的字符们

    其实,之前我一直以为 JSON 会把 ASCII 可显示字符以外的统统转义为 Unicode,直到有一次我用 JSON.stringify 才发现,其实是 PHP 为我们想的太周到了. 我以前是一位 ...

  7. 为ASP.NET控件加入快捷菜单

    ContextMenu Control 快捷菜单控件概述: MSDN Liabrary 中包含了几个DHTML快捷菜单的示例.分别提供了对这一功能的不能实现方法.一个快捷菜单就是在页面中任何位置的一组 ...

  8. shell 判断脚本参数

    测试登陆脚本 ./test.sh -p 123 -P 3306 -h 127.0.0.1 -u root #!/bin/sh ];then echo "USAGE: $0 -u user - ...

  9. HDU 1262 寻找素数对 模拟题

    题目描述:输入一个偶数,判断这个偶数可以由哪两个差值最小的素数相加,输出这两个素数. 题目分析:模拟题,注意的是为了提高效率,在逐个进行判断时,只要从2判断到n/2就可以了,并且最好用打表法判断素数. ...

  10. CentOS7 关闭防火墙和selinux

    本文将简单介绍在CentOS7上如何临时和永久关闭防火墙和selinux. 关闭防火墙 # 查看防火墙状态 [root@localhost ~]# systemctl status firewalld ...