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. insserv: Script <name> is broken: incomplete LSB comment.

    insserv: Script <name> is broken: incomplete LSB comment. insserv: missing `Required-Start:' e ...

  2. IDE和SDK

    像我这种不是专科班出来的,真的很多概念都不太清楚,今天来说说IDE和SDK 简单的来说: IDE(集成开发环境 Integrated Development Environment) 就是我们编写代码 ...

  3. Spring Boot 1.4 单元测试

    在1.3中单元测试这样子的类似代码: // SpringJUnit支持,由此引入Spring-Test框架支持! @RunWith(SpringJUnit4ClassRunner.class) // ...

  4. fastJson顺序遍历JSON字段(转)

    fastJson在把json格式的字符串转换成JSONObject的时候,使用的是HashMap,所以排序规则是根据HASH值排序的,如果想要按照字符串顺序遍历JSON属性,需要在转换的时候指定使用L ...

  5. 通达信zig函数的python实现

    通达信zig函数的python实现 代码 # coding: utf-8 """ Created on Sat Jan 05 18:53:39 2019 http://w ...

  6. asp.net 基于ajaxfileupload.js 实现文件异步上传

    前台代码: /*修改头像*/       //上传       function _sc() {           $(".ckfile").html("") ...

  7. Oracle 查看锁表进程_杀掉锁表进程 [转]

    查看锁表进程SQL语句1: select sess.sid, sess.serial#, lo.oracle_username, lo.os_user_name, ao.object_name, lo ...

  8. 玩转Hook——Android权限管理功能探讨(二)

    距离我上一篇研究ptrace的随笔http://www.cnblogs.com/zealotrouge/p/3544147.html已经过去半年了,最近不忙的时候抽空继续研究了下.同样,参考了Prad ...

  9. Flask源码解析:Flask上下文

    一.上下文(Context) 什么是上下文: 每一段程序都有很多外部变量.只有像Add这种简单的函数才是没有外部变量的.一旦你的一段程序有了外部变量,这段程序就不完整,不能独立运行.你为了使他们运行, ...

  10. shell中后台进程管理: ps -aux 详解

    常用 查找进程id方法:      ps -aux | grep "jupyter"                杀进程:   kill -9 具体的PID 1.ps命令 要对进 ...