Java I/O(2):NIO中的Channel
您好,我是湘王,这是我的云海天,欢迎您来,欢迎您再来~
为了解决标准Java I/O令人难以忍受的效率问题,从JDK1.4开始,NIO出现了(Non-blocking I/O,官方称之为New I/O)。NIO不但新增加了许多全新的类,而且还对原来的很多类进行了改写。之所以是NIO,是因为使用它的场景众多,譬如开发中必不可少的Tomcat,以及大名鼎鼎的Netty,而Netty更是把NIO发挥到了极致,成为了RPC技术事实上的标准,所以它在JDK1.7中又升级为了AIO(NIO2)。
NIO主要有三大核心部分:
- Channel(通道)
- Buffer(缓冲区)
- Selector(选择器/多路复用器)
传统I/O基于字节流或字符流进行操作,而NIO基于新的Channel和Buffer进行操作。这是它们的比较:
至于原理,不用记,可以这么来理解(我始终秉持的态度是:如果你在大厂是自研类RPC系统或类MQ中间件的,那这个一定要精通;否则理解就好,不必死磕):
可以看到,I/O就像个直肠子,直来直去,对数据流完全是来者不拒,来多少接多少,也不管能不能处理得了,这样极容易造成线程阻塞,也就是电脑卡顿。
而NIO就有点弯弯绕了,它告诉线程:“如果我忙不过来就别等我,你先忙你的”。所以,按照这个约定,如果线程发现它不搭理自己的时候就会去忙别的。不会造成信息堵车。
Channel接口最重要的实现可以分为两大类:用于本地文件和用于网络的Channel。
- FileChannel:用于本地文件数据的读写
- DatagramChannel:用于网络UDP数据的读写
- SocketChannel:客户端用于实现网络TCP数据的读写
- ServerSocketChannel:服务端用于监听网络TCP的连接请求,每个请求会创建会一个SocketChannel(即客户端连接)
这是和Channel相关的继承结构图:
I/O本就枯燥,如果只是空洞说技术原理就更毫无价值,还是上代码,把NIO和IO比较一下。
创建一个普通的Java项目:
然后随便在网上或者自己电脑上找一个大文件,比如小电影之类的,写这样的代码:
// 把file1中的内容写到file2中去,看看耗时 // I/O读写 long start = System.currentTimeMillis(); try { FileInputStream fis = new FileInputStream("你电脑上已经存在的文件路径,例如C:\file1"); FileOutputStream fos = new FileOutputStream("你电脑上还不存在的文件路径,例如C:\file2"); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(fis), 1024); String line = null; while ((line = bufferedReader.readLine()) != null) { fos.write(line.getBytes()); } fis.close(); fos.close(); } catch (IOException e) { e.printStackTrace(); } long end = System.currentTimeMillis(); System.out.println(end - start);