同步与异步:同步是一种可靠的有序运行机制,当我们进行同步操作时,后续的任务是等待当前调用返回,才会进行下一步;而异步则相反,其他任务不需要等待当前返回,通常依靠事件,回调等机制来实现任务间次序关系。

阻塞和非阻塞:在进行阻塞操作时,当前线程会处于阻塞状态,无法从事其他任务,只有当条件就绪才能继续,比如ServerSocket新链接建立完毕,或者数据读取,写入操作完成,而非阻塞则是不管IO操作是否结束,直接返回,相应操作在后台继续处理。

IO流(同步、阻塞),前面的文章已经详细介绍过,想知道的可以去前面查阅。

NIO(同步、非阻塞)

NIO的三个主要组成部分:Channel(通道),Buffer(缓冲区),Selector(选择器)

Channel(通道):是一个对象,可以通过他读取和写入数据,可以把它看做是IO中的流,不同的是

-Channel是双向的,即可以读又可以写,而流水单向的

-Channel可以进行异步读写

-Channel的读写必须通过Buffer对象。

Channel的类型:

-FileChannel:从文件读取数据

-DatagramChannel:读写UDP网络协议数据

-SocketChannel:读写TCP网络协议数据

-ServerSocketChannel:可以监听TCP连接

Buffer(缓冲区):是一个对象,包含了一些药写入或者读到Stream对象的。应用程序不能直接对Channel进行读写操作,而必须通过Buffer来进行,即Channel是通过Buffer来读写数据的

使用Buffer读写数据一般遵循以下四个步骤:

1、写入数据到Buffer

2、调用flip()方法

3、从Buffer中读取数据

4、调用clear()方法或者conpact()方法

Buffer的类型:

-ByteBuffer

-CharBuffer

-DoubleBuffer

-FloatBuffer

-IntBuffer

-LongBuffer

-ShortBuffer

Selector(选择器):是一个对象,他可以注册到很多Channel上,监听各个Channel上发生的事件,并且能够根据事件情况决定Channel读写。这样,通过一个线程管理多个Channel,就可以处理大量网络连接。

优点:有了Selector,我们就可以利用一个线程来处理所有的channels。线程之间的切换对操作系统来说代价上很高的,并且每个线程也会占用一定的系统资源。所以对系统来说使用的线程越少越好。

使用方式:

1、创建一个Selector

2、注册Channel到Selector,调用channel.register()方法

注意:注册到Channel必须设置成异步模式才可以,否则异步IO就无法工作,这就意味着我们不能把一个FileChannel注册到Selector,因为FileChannel没有异步模式,但是网络编程中的SocketChannel是可以的。

注册后的返回值是一个SelectionKey。SelectionKey代表这个通道在此Selector上注册,当某个Selector通知您某个传入事件时,它是通过提供对应于该事件的SelectionKey来进行的。

SelectionKey包含如下属性:

Interest set:你要选择的感兴趣的事件的集合

ready set:通道已经准备就绪的集合

Channel:注册的Channel

Selector:获得Selector

attached object:可以将一个对象或者更多信息attach到SelectionKey上

NIO多路复用:

主要步骤和元素:

1、通过Selector.open()创建一个Selector,作为类似调度员的角色

2、创建一个ServerSocketChannel,并且向Selector注册,通过指定SelectionKey.OP_ACCEPT告诉调度员,他关注的是新的连接请求

3、Selector阻塞在select操作,当有Channel发生接入请求,就会被唤醒

4、在具体的方法中,通过SocketChannel和Buffer进行数据操作。

09-26 08:55