Hollis知识星球的一些学习笔记,有兴趣的朋友可以微信搜一下

什么是NIO

什么是IO? 它是指计算机与外部世界或者一个程序与计算机的其余部分的之间的接口。它对于任何计算机系统都非常关键,因而所有 I/O 的主体实际上是内置在操作系统中的。单独的程序一般是让系统为它们完成大部分的工作。 在 Java 编程中,直到最近一直使用 流 的方式完成 I/O。所有 I/O 都被视为单个的字节的移动,通过一个称为 Stream 的对象一次移动一个字节。流 I/O 用于与外部世界接触。它也在内部使用,用于将对象转换为字节,然后再转换回对象。

什么是NIO? NIO 与原来的 I/O 有同样的作用和目的, 他们之间最重要的区别是数据打包和传输的方式。原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。 面向流 的 I/O 系统一次一个字节地处理数据。一个输入流产生一个字节的数据,一个输出流消费一个字节的数据。为流式数据创建过滤器非常容易。链接几个过滤器,以便每个过滤器只负责单个复杂处理机制的一部分,这样也是相对简单的。不利的一面是,面向流的 I/O 通常相当慢。 一个 面向块 的 I/O 系统以块的形式处理数据。每一个操作都在一步中产生或者消费一个数据块。按块处理数据比按(流式的)字节处理数据要快得多。但是面向块的 I/O 缺少一些面向流的 I/O 所具有的优雅性和简单性。

什么是AIO

Java AIO即Async非阻塞,是异步非阻塞的IO。

什么是BIO

Java BIO即Block I/O , 同步并阻塞的IO。 BIO就是传统的java.io包下面的代码实现。

AIO,BIO,NIO的联系和区别

BIO (Blocking I/O):同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。这里假设一个烧开水的场景,有一排水壶在烧开水,BIO的工作模式就是, 叫一个线程停留在一个水壶那,直到这个水壶烧开,才去处理下一个水壶。但是实际上线程在等待水壶烧开的时间段什么都没有做。

NIO (New I/O):同时支持阻塞与非阻塞模式,但这里我们以其同步非阻塞I/O模式来说明,那么什么叫做同步非阻塞?如果还拿烧开水来说,NIO的做法是叫一个线程不断的轮询每个水壶的状态,看看是否有水壶的状态发生了改变,从而进行下一步的操作。

AIO ( Asynchronous I/O):异步非阻塞I/O模型。异步非阻塞与同步非阻塞的区别在哪里?异步非阻塞无需一个线程去轮询所有IO操作的状态改变,在相应的状态改变后,系统会通知对应的线程来处理。对应到烧开水中就是,为每个水壶上面装了一个开关,水烧开之后,水壶会自动通知我水烧开了。

BIO实现文件读写

直接代码实现:

package com.wzlove.bio;

import java.io.Serializable;

/**
* @author 王智
* @date 2018/7/31
* @描述 用户实体类
*/
public class User implements Serializable { private static final long serialVersionUID = -7521946815608679573L;
private String name; private int age; public User() {
} @Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public User(String name, int age) {
this.name = name;
this.age = age;
}
} package com.wzlove.bio; import java.io.*; /**
* @author 王智
* @date 2018/7/31
* @描述 用来测试BIO
* BIO : Java BIO即Block I/O , 同步并阻塞的IO。 测试BIO
* 其实BIO 也就是我们时常说的序列化流和反序列化流
*/
public class BIODemo { public static void main(String[] args){ // 使用输出流进行写入到文件中
User user = new User("王智",23);
try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("test.txt"))) {
// 写入
oos.writeObject(user); } catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} // 使用输入流进行读取
try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream("test.txt"))) {
// 进行信息的读取
User user1 = (User)ois.readObject();
System.out.println(user1);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}

需要注意的是,写入的读取的对象必须实现Serializable接口,生成serialVersionUID,还有无参构造,都要存在.

NIO实现文件的读写

package com.wzlove.nio;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset; /**
* @author 王智
* @date 2018/7/31
* @描述 NIO 以块的方式处理数据
* 使用的方法有:
* ByteBuffer的常用方法:
* static ByteBuffer allocate(int capacity) 分配一个新的字节缓冲区。
* int capacity() 返回此缓冲区的容量。
* int position() 返回此缓冲区的位置。
* int read(ByteBuffer dst) 从该通道读取到给定缓冲区的字节序列。
* Charset的常用方法:
* Charset forName(String charsetName) 返回名为charset的charset对象。
* ByteBuffer encode(String str) 在此字符集中将字符串编码为字节的便捷方法。
*/
public class NIODemo {
public static void main(String[] args) {
writeNIO();
System.out.println("===========================================/");
readNIO();
} /**
* 步骤 :
* 1.使用输入流创建文件通道
* 2. 创建字节缓冲区
* 3. 开始读取内容
* 4. 将读取的内容转化为字节数组,使用System.out的write方法输出
*/
public static void readNIO(){
try (
// c创建文件通道
FileChannel fc = new FileInputStream("nio.txt").getChannel()
) {
// 创建字节缓冲区(static ByteBuffer allocate(int capacity)分配一个新的字节缓冲区。指定缓冲区的大小 )
ByteBuffer bb = ByteBuffer.allocate(100);
// 输出缓冲区的大小
System.out.println("输入缓冲区的大小为 : " + bb.capacity());
// 输出缓冲区的限制大小
System.out.println("输入缓冲区的限制大小为 : " + bb.limit());
// 输出缓冲区的位置
System.out.println("输入缓冲区的位置 : " + bb.position());
// 进行文件的读取
int length = -1;
while((length = fc.read(bb)) != -1){
/*
* 注意,读取后,将位置置为0,将limit置为容量, 以备下次读入到字节缓冲中,从0开始存储
*/
bb.clear();
byte[] bytes = bb.array();
System.out.write(bytes,0,length);
System.out.println();
// 输出缓冲区的大小
System.out.println("输入缓冲区的大小为 : " + bb.capacity());
// 输出缓冲区的限制大小
System.out.println("输入缓冲区的限制大小为 : " + bb.limit());
// 输出缓冲区的位置
System.out.println("输入缓冲区的位置 : " + bb.position());
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
} /**
* 步骤:
* 1. 使用输出流创建文件通道
* 2. 创建字节缓冲区
* 3. 开始进行写入
*/
public static void writeNIO(){ try (
// 创建FileChannel通道(使用try-with-resouce的形式)
FileChannel fc = new FileOutputStream("nio.txt").getChannel() ) {
// 按照指定的编码和内容创建字节缓冲区
ByteBuffer bb = Charset.forName("UTF-8").encode("你好啊,世界,我爱你,世界");
// 输出初始化容量
System.out.println("初始化容量 : " + bb.capacity());
// 输出缓冲区的限制大小
System.out.println("缓冲区的限制为 : " + bb.limit());
int len = 0;
// 标准的写入文件的代码
while((len = fc.write(bb)) != 0){
/*
* 注意,这里不需要clear,将缓冲中的数据写入到通道中后 第二次接着上一次的顺序往下读
*/
System.out.println("写入的长度为 : " + len);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}

AIO实现文件的读写(不是特别理解)

public class AioWrite {

    public static void main(String[] args) throws Exception {
// AsynchronousFileChannel用于读取,写入和操作文件的异步通道。当通过调用此类定义的open方法之一来打开文件时,将创建异步文件通道。
// static AsynchronousFileChannel open(Path file, OpenOption... options) 打开或创建用于读取和/或写入的文件,返回异步文件通道以访问该文件。
/*
StandardOpenOption枚举类:
APPEND 如果文件打开 WRITE访问,则字节将被写入文件的末尾而不是开头。
CREATE 创建一个新文件(如果不存在)。
CREATE_NEW 创建一个新的文件,如果该文件已经存在失败。
DELETE_ON_CLOSE 关闭时删除。
DSYNC 要求将文件内容的每次更新都与底层存储设备同步写入。
READ 打开阅读权限。
SPARSE 稀疏文件
SYNC 要求将文件内容或元数据的每次更新都同步写入底层存储设备。
TRUNCATE_EXISTING 如果文件已经存在,并且打开 WRITE访问,则其长度将截断为0。
WRITE 打开以进行写入。
*/
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(
Paths.get("asynchronous.txt"), StandardOpenOption.READ,
StandardOpenOption.WRITE, StandardOpenOption.CREATE);
/*
CompletionHandler 用于消除异步I / O操作结果的处理程序。
在此包中定义的异步通道允许指定完成处理程序以消耗异步操作的结果。 当I / O操作成功完成时,
将调用completed方法。 如果I / O操作失败,则调用failed方法。 这些方法的实现应该及时完成,
以避免将调用线程调度到其他完成处理程序。
*/
CompletionHandler<Integer, Object> handler = new CompletionHandler<>() { @Override
public void completed(Integer result, Object attachment) {
System.out.println("Attachment: " + attachment + " " + result
+ " bytes written");
System.out.println("CompletionHandler Thread ID: "
+ Thread.currentThread().getId());
} @Override
public void failed(Throwable e, Object attachment) {
System.err.println("Attachment: " + attachment + " failed with:");
e.printStackTrace();
}
}; System.out.println("Main Thread ID: " + Thread.currentThread().getId());
// abstract <A> void write(ByteBuffer src, long position, A attachment, CompletionHandler<Integer,? super A> handler)
// 从给定的缓冲区向给定的文件位置开始,向该通道写入一个字节序列。
// static ByteBuffer wrap(byte[] array) 将一个字节数组包装到缓冲区中。
fileChannel.write(ByteBuffer.wrap("Sample".getBytes()), 0, "First Write",
handler);
// 第一次写入Sample,第二次写入也是从索引0位置开始的,所以讲Sam覆盖掉了,变为Box,所以结果为Boxple
fileChannel.write(ByteBuffer.wrap("Box".getBytes()), 0, "Second Write",
handler); }
} public class AioReader { public static void main(String[] args) throws Exception {
// Path可用于在文件系统中定位文件的对象。 它通常表示系统相关的文件路径
Path file = Paths.get("asynchronous.txt");
// AsynchronousFileChannel是用于读取,写入和操作文件的异步通道。
AsynchronousFileChannel channel = AsynchronousFileChannel.open(file);
// 创建字节缓冲区,指定缓冲区的大小
ByteBuffer buffer = ByteBuffer.allocate(100_000);
// Future接口,A Future计算的结果。 提供方法来检查计算是否完成,等待其完成,并检索计算结果
Future<Integer> result = channel.read(buffer, 0);
// boolean isDone() 返回 true如果任务已完成
while (!result.isDone()) {
// 暂时不了解
ProfitCalculator.calculateTax();
}
// V get() 等待计算完成,然后检索其结果。
Integer bytesRead = result.get();
// 输出文件内容的字节长度
System.out.println("Bytes read [" + bytesRead + "]");
}
} class ProfitCalculator {
public ProfitCalculator() {
}
public static void calculateTax() {
}
}

Java之NIO,BIO,AIO的更多相关文章

  1. java IO NIO BIO 最权威的总结

    1. BIO (Blocking I/O) 1.1 传统 BIO 1.2 伪异步 IO 1.3 代码示例 1.4 总结 2. NIO (New I/O) 2.1 NIO 简介 2.2 NIO的特性/N ...

  2. java的NIO和AIO

    1. 什么是NIO NIO是New I/O的简称,与旧式的基于流的I/O方法相对,从名字看,它表示新的一套Java I/O标 准.它是在Java 1.4中被纳入到JDK中的,并具有以下特性: NIO是 ...

  3. 【转载】Java NIO学习 & NIO BIO AIO 比较

    可以参考这个页面: http://www.iteye.com/magazines/132-Java-NIO (下面这个页面也有) http://ifeve.com/overview/ 另,在这篇文章里 ...

  4. Java BIO、NIO、AIO 学习(转)

    转自 http://stevex.blog.51cto.com/4300375/1284437 先来个例子理解一下概念,以银行取款为例: 同步 : 自己亲自出马持银行卡到银行取钱(使用同步IO时,Ja ...

  5. JAVA中IO技术:BIO、NIO、AIO

    1.同步异步.阻塞非阻塞概念        同步和异步是针对应用程序和内核的交互而言的. 阻塞和非阻塞是针对于进程在访问数据的时候,根据IO操作的就绪状态来采取的不同方式,说白了是一种读取或者写入操作 ...

  6. Java IO 之 BIO、NIO、AIO

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

  7. (转)Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    原文出自:http://blog.csdn.net/anxpp/article/details/51512200 1.BIO编程 1.1.传统的BIO编程 网络编程的基本模型是C/S模型,即两个进程间 ...

  8. Java 网络IO编程总结(BIO、NIO、AIO均含完整实例代码)

    本文会从传统的BIO到NIO再到AIO自浅至深介绍,并附上完整的代码讲解. 下面代码中会使用这样一个例子:客户端发送一段算式的字符串到服务器,服务器计算后返回结果到客户端. 代码的所有说明,都直接作为 ...

  9. Java提高班(五)深入理解BIO、NIO、AIO

    导读:本文你将获取到:同/异步 + 阻/非阻塞的性能区别:BIO.NIO.AIO 的区别:理解和实现 NIO 操作 Socket 时的多路复用:同时掌握 IO 最底层最核心的操作技巧. BIO.NIO ...

随机推荐

  1. shell--read命令

    read命令 -p(提示语句) -n(字符个数) -t(等待时间) -s(不回显) 1.基本读取read命令接收标准输入(键盘)的输入,或其他文件描述符的输入(后面在说).得到输入后,read命令将数 ...

  2. Vue的computed计算属性是如何实现的

    一个开始 有如下代码,full是一个计算属性,开始,他的值是'hello world',1s后,msg变成了‘I like’, full的值同步变成了'I like world';其原理解析来看一下. ...

  3. 团队项目M1阶段个人反思

    郑培蕾: 作为项目的PM,我前期的工作还是有很大的缺陷的,因为没有在开发之前对项目进行一个合理的评估,所以后来分配任务的时候就很不科学, 而且任务分配的比较粗糙,没有细化到每个人每天应该做什么,这就导 ...

  4. 【Alpha】Task分配与计划发布

     团队项目链接 以上大概是我们的任务分配,根据目前的预计时间来看,到α版本项目稳定下来至少需要440小时的开发时间才能完成. 项目最大的问题点和难点在于其数据量非常之大,计算模块要求非常之多,想象一下 ...

  5. 20172322 实验一《Java开发环境的熟悉》实验报告

    172322 2017-2018-2 <程序设计与数据结构>实验一报告 课程:<程序设计与数据结构> 班级: 1723 姓名: 张昊然 学号:20172322 实验教师:王志强 ...

  6. eg_6

    问题描述: 将一句话的单词进行倒置,标点不倒置.比如 I like beijing. 经过函数后变为:beijing. like I Demo1: import java.util.Scanner; ...

  7. week3c:个人博客作业

    程序测试: 一个基本的测试. 在Visual Studio 2013 中使用C++单元测试 操作如下: 这是我学到的过程. 有复杂程序的测试.以后有时间再弄.

  8. 05_Java基础语法_第5天(方法)_讲义

    今日内容介绍 1.方法基础知识 2.方法高级内容 3.方法案例 01方法的概述 * A: 为什么要有方法 * 提高代码的复用性 * B: 什么是方法 * 完成特定功能的代码块. 02方法的定义格式 * ...

  9. 基于Freemarker的eclipse plugin代码生成器插件开发

    固定类型的软件写多了,里面总是有一些复制粘贴改变类名改变量的基础文件,相似程度非常高.作为一名程序员,坚持不多写一行重复代码的精神,写了一个Eclipse的代码生成器插件.插件通过在xml文件中配置的 ...

  10. php框架的制作原理

    php框架的制作原理 (2012-08-16 14:25:55) 转载▼ 标签: php框架制作 杂谈 分类: php index.php 主入口文件 <?php  define('ISEXIS ...