https://www.jianshu.com/p/c5e16460047b
Demo 源码:
https://github.com/huangzhenshi/IO_NIO_NIO2Demo
名词解释
异步非阻塞IO:主线程向操作系统发起一个异步IO操作,并指定回调操作(CompletionHandler),然后就可以做别的事情了,操作系统执行完IO操作之后,会创建一个子线程执行回调的方法。
异步阻塞IO:将来式异步IO,主线程向操作系统发起一个异步IO操作,并返回一个future对象,主线程可以根据业务需求,在任意的操作时机,阻塞式的获取IO操作的结果。
BIO NIO AIO适用场景
BIO方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序直观简单易理解;
NIO方式适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,并发局限于应用中,编程比较复杂,JDK1.4开始支持;
AIO方式适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持
AIO 新特性
- 基于Path的复制、移动、删除
- 获取和改变文件的属性(RW读写属性、最后修改时间和大小)
- 递归目录功能
- 封装了一些快速简洁读写的方法(Files.readAllLine())
- 支持异步IO(包括文本IO和Socket IO),将来式(异步阻塞)和回调式(异步非阻塞)
- 文件监听类,监听某文件发生改变(WatchService)
channel
- AsynchronousFileChannel: 用于文件异步读写;
- AsynchronousSocketChannel: 客户端异步socket;
- AsynchronousServerSocketChannel: 服务器异步socket。
回调式
主线程会派一个侦查员CompletionHandler到独立的线程中执行IO操作。
public abstract void read(dst,position, attachment,CompletionHandler);
public static void readAioCallBackStyle() throws IOException, InterruptedException{ Path path = Paths.get(fileFrom); AsynchronousFileChannel channel = AsynchronousFileChannel.open(path); ByteBuffer buffer = ByteBuffer.allocate(1024); channel.read(buffer, 0, buffer, new CompletionHandler<Integer, ByteBuffer>() { @Override public void completed(Integer result, ByteBuffer attachment) { attachment.flip(); byte[] data = new byte[attachment.limit()]; attachment.get(data); System.out.println(new String(data)); attachment.clear(); System.out.println(Thread.currentThread().getName() + " read success!"); } @Override public void failed(Throwable exc, ByteBuffer attachment) { System.out.println("read error"); } }); System.out.println("工作交代完了"); }
|
将来式
样子像NIO,只是底层实现原理不同
public abstract Future read(ByteBuffer dst, long position);
//异步将来式读取文本,主线程通过返回的Future对象来按照自己的时机去检查结果 public static void readAioFutureStyle() throws IOException, InterruptedException, ExecutionException{ Path path = Paths.get(fileFrom); AsynchronousFileChannel channel = AsynchronousFileChannel.open(path); ByteBuffer buffer = ByteBuffer.allocate(30460); Future<Integer> future = channel.read(buffer,0); while(!future.isDone()); buffer.flip(); byte[] data = new byte[buffer.limit()]; buffer.get(data); System.out.println(new String(data)); buffer.clear(); }
|
文件操作
Path类
可以指向文件或文件夹,很多情况下,可以用Path来代替File类
Files类
支持超级简单的文件写入,比如往某文件中,写一句话
Path file=Paths.get("C:\\huangzs\\Demos", "test.txt"); Files.write(file, "hello".getBytes());
|
文件复制(不仅支持文本文件、也支持图片、音频、视频等文件)
Path sourcePath= Paths.get(fileFrom); Path descPath= Paths.get(fileTo); Files.copy(sourcePath, descPath);
|
基于Path的删除
Path descPath= Paths.get("C:\\Users\\502764158\\Desktop","testCopy.jpg"); Files.deleteIfExists(descPath);
|
文本文件读取
List<String> lines = Files.readAllLines(path, charset);
|