高并发之NIO、 AIO、BIO
来源:互联网 发布:mac电脑flash过期 编辑:程序博客网 时间:2024/06/08 18:31
1. 什么是NIO
NIO是New I/O的简称,与旧式的基于流的I/O方法相对,从名字看,它表示新的一套Java I/O标 准。它是在Java 1.4中被纳入到JDK中的,并具有以下特性:
- NIO是基于块(Block)的,它以块为基本单位处理数据 (硬盘上存储的单位也是按Block来存储,这样性能上比基于流的方式要好一些)
- 为所有的原始类型提供(Buffer)缓存支持
- 增加通道(Channel)对象,作为新的原始 I/O 抽象
- 支持锁(我们在平时使用时经常能看到会出现一些.lock的文件,这说明有线程正在使用这把锁,当线程释放锁时,会把这个文件删除掉,这样其他线程才能继续拿到这把锁)和内存映射文件的文件访问接口
- 提供了基于Selector的异步网络I/O
java中,同步就是说多线程去访问某个方法的时候,当访问到某些共享数据是同一时刻只能有一个线程去访问
阻塞就是说当前线程被挂起,例如调用了Thread.sleep() ;
Java NIO和IO的主要区别下表总结了Java NIO和IO之间的主要差别,我会更详细地描述表中每部分的差异。IO NIO面向流 面向缓冲(块)同步阻塞IO 同步 非阻塞IO无 选择器面向流与面向缓冲Java NIO和IO之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。 Java NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。阻塞与非阻塞IOJava IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 Java NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此,一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。
package entryNIO;import java.io.FileInputStream;import java.io.FileOutputStream;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;public class BufferAndChannel {public static void main(String[] args) {String string="C:\\Users\\hp\\Desktop";long startTime=System.currentTimeMillis();nioCopyFile(string+"\\FileChannelImpl.java",string+"\\1.java");System.out.println("用时:"+(System.currentTimeMillis()-startTime)+"毫秒");System.out.println("读取完毕");}public static void nioCopyFile(String resource, String destination) {ByteBuffer buffer = null;//字节缓冲区try(//JDK 1.7 新特性 try-with-resource ,凡是实现了Closeable接口就可以用这种写法,而无需关闭流FileInputStream fis = new FileInputStream(resource);FileOutputStream fos = new FileOutputStream(destination);// Used by FileInputStream.getChannel() and RandomAccessFile.getChannel()FileChannel readChannel = fis.getChannel(); // 读文件通道FileChannel writeChannel = fos.getChannel(); // 写文件通道){buffer=ByteBuffer.allocate(1024*1024); // 为字节缓冲区分配空间int len=0;while ((len = readChannel.read(buffer))!=-1) {/* 反转此缓冲区。首先将限制设置为当前位置,然后将位置设置为 0。如果已定义了标记,则丢弃该标记。 在一系列通道读取或放置 操作之后,调用此方法为一系列通道写入或相对获取 操作做好准备。例如: 当将数据从一个地方传输到另一个地方时,经常将此方法与 compact 方法一起使用。 */buffer.flip();//反转此缓冲区writeChannel.write(buffer); // 写入文件buffer.clear();//清空缓冲区}} catch (Exception e) {e.printStackTrace(); } }}//理论上会比使用BufferedReader等快一点
package entryNIO;import java.nio.ByteBuffer;public class BufferAndChannel {public static void main(String[] args) {long startTime=System.currentTimeMillis();try {Ha.main(args);} catch (Exception e) {e.printStackTrace();}System.out.println("用时:"+(System.currentTimeMillis()-startTime)+"毫秒");System.out.println("读取完毕");}}class Ha{public static void main(String[] args) throws Exception {ByteBuffer b = ByteBuffer.allocate(15); // 15个字节大小的缓冲区sop(b);//打印for (int i = 0; i < 10; i++) {// 存入10个字节数据b.put((byte) i);}sop(b);/* 该操作会重置position,通常,将buffer从写模式转换为读 模式时需要执行 flip()方法 该方法不仅重置了当前的position为0,还将limit设置到当前position的位置 。 limit的意义在于,来确定哪些数据是有意义的,换句话说,从position到limit之间的数据才是有意义的数据, 因为是上次操作的数据。所以flip操作往往是读写转换的意思。 */b.flip(); // 重置position,一般会重置为0sop(b);for (int i = 0; i < 5; i++) {System.out.print(b.get());}System.out.println();sop(b);b.flip();sop(b);}private static void sop(ByteBuffer b) { //这里要区别下容量和上限,比如一个Buffer有15KB,那么15KB就是容量,我将5KB的文件读到Buffer中,那么上限就是5KB。System.out.println("limit=" + b.limit() + " capacity=" + b.capacity()+ " position=" + b.position());}}
将文件映射到内存
package entryNIO;import java.io.RandomAccessFile;import java.nio.MappedByteBuffer;import java.nio.channels.FileChannel;public class BufferAndChannel {public static void main(String[] args) {long startTime = System.currentTimeMillis();try (RandomAccessFile raf = new RandomAccessFile("C:\\FileChannelImpl.java", "rw"); FileChannel fc = raf.getChannel();) {// 将文件映射到内存中MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, 0, raf.length());//byte[] byteArray=new byte[1024*1024];while (mbb.hasRemaining()) {// between the current position and the limit.在这范围内是否还有System.out.print((char) mbb.get());//mbb.get(dst, offset, length)}mbb.put(0, (byte) 98); // 修改文件} catch (Exception e) {e.printStackTrace();}System.out.println("用时:" + (System.currentTimeMillis() - startTime) + "毫秒");System.out.println("读取完毕");}}
阅读全文
0 0
- 高并发之NIO、 AIO、BIO
- java高并发程序设计学习笔记八BIO、NIO和AIO
- Java提高篇之BIO、NIO、AIO
- Java之IO,BIO,NIO,AIO
- Java高并发程序设计笔记10之NIO和AIO
- BIO/AIO/NIO
- BIO AIO NIO
- BIO,NIO,AIO
- BIO、NIO、AIO区别
- java BIO NIO AIO
- BIO NIO AIO
- Java BIO、NIO、AIO
- java BIO NIO AIO
- Java BIO/NIO/AIO
- java bio nio aio
- BIO、NIO、AIO
- java nio aio bio
- java nio bio aio
- 游戏图像学基础 实践经验和优化(一)
- ZooKeeper选举机制
- 从产品的角度看中国有嘻哈的火爆
- Spark学习笔记(5)Spark Streaming流计算框架的运行源码
- POJ 1703 Find them, Catch them
- 高并发之NIO、 AIO、BIO
- Html-1-标准的HTML5代码样式
- (算法题)一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
- 从一个字符串中删除所有的某个字符
- 哈工大计算机学院实验室的情况介绍
- 多线程间的同步
- caioj1064·动态规划入门(一维一边推2:最长上升子序列)
- 程序员技术晋升非正式攻略
- bootstrap环境搭建两种方法之一