NIO是什么

  • JDK1.4以后提供的新的IO操作API,可以叫做new IO(新的IO)或者说Non Blocking IO(非阻塞的IO)。
  • NIO面向缓冲区(Buffer),基于通道(Channel)的IO操作,多通道之间使用选择器(Selectors)读写操作更加高效。

传统IO和NIO的区别

IO NIO
面向流(Stream Oriented) 面向缓存区(Buffere Oriented)
阻塞IO(Blocking IO) 非阻塞IO(Non Blocking IO)
选择器(Select)

流和缓冲区
数据流流动和分批次流动的区别,举个例子,把数据比作人群,数据流就是人流,缓冲区就是高铁或者飞机,两地之间人员流动,肯定是高铁或飞机快。

阻塞和非阻塞

  • 阻塞/非阻塞关注的是程序在等待调用结果(消息,返回值)时的状态.
  • 阻塞调用是指调用结果返回之前,当前线程会被挂起。调用线程只有在得到结果之后才会返回。
  • 非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

同步和异步

  • 同步/异步关注的是消息通信机制 (synchronous communication/ asynchronous communication) 。
  • 所谓同步,就是在发出一个调用时,在没有得到结果之前, 该调用就不返回。
  • 异步则是相反,调用在发出之后,这个调用就直接返回了,所以没有返回结果

举个例子,你去买饭,同步阻塞就是你自己去排队买饭;异步阻塞就是你让别人帮你去排队买饭;同步非阻塞就是你去买饭,付完款等待叫号;异步非阻塞就是你叫了个外卖,外卖人员去了叫号取餐。

快速上手

先写个demo,对比一下io和nio两种方式拷贝一个文件

  1. @Test
  2. void ionio复制文件对比() throws IOException {
  3. //文件大小 64M
  4. //mac pro电脑
  5. String sourcePath = "/Users/liupeng/IdeaProjects/test/1.bin";
  6. String desPath = "/Users/liupeng/IdeaProjects/test/2.bin";
  7. File source = new File(sourcePath);
  8. File des = new File(desPath);
  9. if (!des.exists()) {
  10. des.createNewFile();
  11. }
  12. long start1 = System.currentTimeMillis();
  13. copyFileIO(source, des);
  14. long end1 = System.currentTimeMillis();
  15. System.out.println("io方式:" + (end1 - start1) + "毫秒");
  16. long start2 = System.currentTimeMillis();
  17. copyFileNIO(source, des);
  18. long end2 = System.currentTimeMillis();
  19. System.out.println("nio方式:" + (end2 - start2) + "毫秒");
  20. //输出:
  21. //io方式:9710毫秒
  22. //nio方式:240毫秒
  23. }
  24. private void copyFileIO(File source, File des) throws IOException {
  25. BufferedInputStream bis = new BufferedInputStream(new FileInputStream(source));
  26. BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(des));
  27. //将数据源读到的内容写入目的地--使用数组
  28. byte[] bytes = new byte[1024 * 1024];
  29. int len;
  30. while ((len = bis.read(bytes)) != -1) {
  31. bos.write(bytes, 0, len);
  32. }
  33. }
  34. private void copyFileNIO(File source, File des) throws IOException {
  35. RandomAccessFile read = new RandomAccessFile(source, "rw");
  36. RandomAccessFile write = new RandomAccessFile(des, "rw");
  37. FileChannel readChannel = read.getChannel();
  38. FileChannel writeChannel = write.getChannel();
  39. // ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024);//1M缓冲区 分配到jvm内存
  40. ByteBuffer byteBuffer = ByteBuffer.allocateDirect(1024 * 1024);//1M缓冲区 直接分配到os内存
  41. while (readChannel.read(byteBuffer) > 0) {
  42. byteBuffer.flip();
  43. writeChannel.write(byteBuffer);
  44. byteBuffer.clear();
  45. }
  46. writeChannel.close();
  47. readChannel.close();
  48. }

NIO主要的三个概念

  1. 缓冲区 Buffer
  2. 通道 Channel
  3. 选择器 Selector

    假如把数据流比作人流,可以理解为,通道就是火车轨道,缓冲区就是高铁,指挥中心就是选择器。