选择器(Selector)的 作用:将通道感兴趣的事件放入队列中,而不是马上提交给应用程序,等已注册的通道自己来请求处理这些事件。换句话说,就是选择器将会随时报告已经准备好了的通道,而且是按照先进先出的顺序。
open()
方法,
静态方法,用于获取1个Selector对象
keys()
方法,用于获取所有注册到Selector对象上的SelectionKey
selectedKeys()
方法,用于获取已注册通道发出的准备好了的SelectionKey
select()
方法,调用此方法的线程会一直阻塞,直到注册的通道中关注的事件发生了才会返回。 例:服务端的ServerSocketChannel
注册了OP_ACCEPT
事件,如果没有客户端连接服务端,那么服务端将一直阻塞在调用select()
方法的地方
select(long)
方法,此方法与不带参数的差不多,参数的含义是当阻塞的时间超过给定的时间参数,该方法将返回继续执行
wakeup()
方法,会唤醒当前被阻塞的线程,使其 select() 立即返回;如果当前线程没有阻塞,那么执行了wakeUp() 方法之后,下一个线程的 select() 方法会被立即返回,不再被阻塞下去。
close()
方法,能够关闭当前的选择器。当一个线程当前呈阻塞状态,那么中止这种状态需要先调用Selector的 wakeUp()
方法。close()方法在实现类中先调用wakeUp()
方法唤醒被阻塞的线程,然后置空所有的通道、所有就绪的SelectionKey,让这个选择器上的轮询组件也闲置下来。
选择键(SelectionKey)的作用是表明哪个通道已经做好了相应的准备,相应的准备指SelectionKey
类里定义的OP_READ
,OP_WRITE
,OP_CONNECT
,OP_ACCEPT
中某个某个事件发生了。Selector不断轮询是否有事件准备好了,如果有事件准备好了则获取事件相应的SelectionKey,进入事件处理
SelectionKey主要说两点:
attach(Object)
主要用于绑定一个对象(
对象可以任意类型),绑定后可以在不同线程间共享,对应的
attachment()
方法用于获取绑定的对象
interestOps()
方法用于获取通道“感兴趣”的操作或事件
说了Selector 与 SelectionKey 的基础知识及主要方法的使用,现在就来实践一下。
服务端
伪代码
1.打开1个ServerSocketChannel通道
2.把ServerSocketChannel设置为非阻塞的
3.为ServerSocketChannel通道绑定ip地址与端口
4.获取Selector对象
5.把ServerSocketC