1,SelectionKey
1)創(chuàng)建SelectionKey
每次channel向selector注冊時,會創(chuàng)建一個SelectionKey。
ssc.register(selector, SelectionKey.OP_ACCEPT);
1.放入Channel的SelectionKey[]數(shù)組keys中
2.放入Selector的Set<SelectionKey>集合keys中
2)合法的ops
image.png
3)SelectionKey包含一個selector和一個channel
selector()方法獲取Selector、channel()方法獲取Channel
image.png
2,Channel向Selector注冊過程
1)注冊步驟如下
image.png
非該channel支持的valid-operation诗祸,拋出異常媒抠。如: ServerSocketChannel只支持SelectionKey.OP_ACCEPT
2)Channel有一個SelectionKey[] keys
的數(shù)組
注冊成功后瞎疼,將返回的SelectionKey放入channel的keys數(shù)組中魄鸦。
image.png
3)Selector有一個Set<SelectionKey> keys集合
注冊成功后,epoll模型將SelectionKey放入selector的keys集合中茅郎。
3蜗元,Channel有效的ops集合
1)DatagramChannel
支持讀、寫事件系冗。
image.png
ServerSocketChannel只支持OP_ACCEPT監(jiān)聽事件奕扣。
image.png
SocketChannel支持讀、寫掌敬、連接事件惯豆。
image.png
3池磁,Selector結(jié)構(gòu)
1)三個SelectionKey的集合
image.png
image.png
2)基于OS的SelectorProvider
1. 在openjdk中,每個操作系統(tǒng)都有一個sun.nio.ch.DefaultSelectorProvider實(shí)現(xiàn)楷兽。
2. 在Linux上是EPollSelectorProvider 地熄,在Mac OS是KQueueSelectorProvider。
3.通過EpollSelectorProvider.openSelector()創(chuàng)建EPollSelectorImpl Selector對象芯杀。
image.png
4端考,Linux epoll模型
1)基礎(chǔ)概念
Selector:IO多路復(fù)用的一個封裝,Linux下就是對epoll系統(tǒng)調(diào)用的封裝揭厚。
epoll本質(zhì):將event loop交給了內(nèi)核却特,網(wǎng)絡(luò)數(shù)據(jù)先到內(nèi)核,內(nèi)核直接處理筛圆,避免系統(tǒng)調(diào)用和數(shù)據(jù)拷貝, 提高性能裂明。
SelectionKey本質(zhì):對IO事件(讀、寫太援、連接闽晦、監(jiān)聽)的封裝,保存Channel關(guān)心的事件粉寞。
image.png
2)epoll系統(tǒng)調(diào)用
image.png
image.png
3)selector.select方法選擇就緒的I/O事件
1. EpollSelectorImpl底層調(diào)用native方法 epollWait尼荆。
2. epollWait 底層發(fā)起epoll_wait系統(tǒng)調(diào)用。
epoll_create:創(chuàng)建一個epollfd唧垦,使用紅黑樹存儲準(zhǔn)備就緒的事件。在EpollSelectorImpl初始化時調(diào)用液样。
epoll_ctl:對新舊事件進(jìn)行新增修改或者刪除振亮。
epoll_wait:等待內(nèi)核返回I/O事件。調(diào)用Selector.select方法時底層調(diào)用鞭莽。
4)NIO的select方法
selector.select()-->底層epoll_wait-->獲取Iterator<SelectionKey>-->遍歷處理每一個IO事件SelectionKey坊秸。
image.png