- 说说NIO的实现原理
答: Java的NIO主要由三个核心部分组成: Channel,Buffer,Selector
基本上,IO在NIO中都是从一个Channel开始. 数据可以从Channel读到Buffer中,也可以从Buffer写到Channel中.Channel有好几种类型,其中常见的有FileChannel,DatagramChannel,SocketChannel,ServerSocketChannel等. 这些通道涵盖了UDP和TCP网络IO以及文件IO
Buffer本质是一块可以写入数据,然后可以从中读取数据的内存. 这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该内存块.
Java NIO里关键的Buffer实现有CharBuffer,ByteBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer. 这些Buffer覆盖了能通过IO发送的基本数据类型,即byte,short,int,long,float,double,char.
Buffer对象包含三个重要的属性,分别是capacity,position,limit.其中position和limit的含义取决于Buffer处在读模式还是写模式. 但不管什么模式,capacity含义总是一样.
- capacity : 作为一个内存块,Buffer有个固定的最大值,就是capacity.Buffer只能写capacity个数据.一旦Buffer满了,需要将其清空才能继续写数据
- position: 当写数据到Buffer时,position表示当前的位置. 初始的position值为0. 当一个数据写到Buffer后,position会向前移动到下一个可插入数据的Buffer单元. position最大可为capacity-1. 当读取数据时,也是从某个特定位置读. 当将Buffer从写模式切换到读模式,position会被重置为0.当从Buffer的position处读取数据时,position向前移动到下一个可读的位置.
- limit: 在写模式下,Buffer的limit表示最多能往Buffer里写多少数据,此时limit等于capacity. 当切换Buffer到读模式时,limit表示最多可以读取的数据量,此时limit会被设置成写模式下的position值
三个属性之间的关系, 如下图所示
三个属性之间的关系
Selector允许单线程处理多个Channel,如果应用打开了多个连接(通道),但每个连接的流量都很低,使用Selector就会很方便.要使用Selector,得向Selector注册Channel,然后调用它的select()方法.这个方法会一直阻塞到某个注册的通道有事件就绪.一旦这个方法返回,线程就可以处理这些事件,事件例如有新连接进来,数据接收等.
例:在一个单线程中使用一个Selector处理3个Channel的图示:
线程使用Selector
- 问: 介绍下Java的序列化与反序列化
答: 序列化可以将对象转换成字节序列,这些字节序列可以保存在磁盘上,也可以在网络中传输,并允许程序将这些字节序列再次恢复成原来的对象. 其中对象的序列话(Serialize)是指将一个Java对象写入IO流中,对象的反序列话(Deserialize),则是指从IO流中恢复该对象.
若对象要支持序列化机制,则它的类需要实现Serializable接口. 该接口是一个标记接口,它没提供任何方法,只是标明该类是可以序列化的,Java的很多类已经实现了Serializable接口,例如包装类,String,Date等.
若要实现序列化,则需要使用对象流,ObjectInputStream和ObjectOutputStream. 其中,在序列化时需要调用ObjectOutputStream对象的writeObject()方法,以输入对象序列. 在反序列化时需要调用ObjectInputStream对象的readObject()方法,将对象序列恢复为对象.
网友评论