很抱歉鸭蛙,這是一篇個(gè)人技術(shù)筆記丐一。單純地記錄, ?沒營養(yǎng)
BUFFER:
ByteBuffer
CharBuffer
DoubleBuffer
FloatBuffer
IntBuffer
LongBuffer
ShortBuffer
MappedByteBuffer,用于表示內(nèi)存映射文件
CHANNEL:
FILECHANNEL
DATAGRAMCHANNEL
SOCKETCHANNEL
SERVERSOCKETCHANNEL
涵蓋TCP茫孔、UDP IO和文件IO
SELECTOR:
在一個(gè)Thread中可以用Selector處理多個(gè)channel叮喳。如果打開了很多連接,每個(gè)連接流量很小缰贝,可以用馍悟。
CHANNEL的數(shù)據(jù)讀寫是單向的,可以異步剩晴,總是需要BUFFERBUFFER锣咒。
關(guān)于它們的簡單用例如下:
File f
Channel c = f.getChannel()
c.read(new ByteBuff())
c.flip()
scatter()?
gather()
channel之間可以直接傳輸數(shù)據(jù):
toChannel.transferFrom(position, count, fromChannel);
fromChannel.transferTo(position, count, toChannel);
Selector概念:
能夠檢測(cè)到多個(gè)channel,并能夠知曉通道是否為讀寫做好準(zhǔn)備赞弥。
為什么使用Selector:
僅用單個(gè)線程控制多個(gè)channel的優(yōu)勢(shì)明顯
Selector使用示例:
Selector selector = Selector.open();
channel.configureBlocking(false);
SelectionKey key = channel.register(selector,Selectionkey.OP_READ);
與Selector一起使用時(shí)毅整,Channel必須處于非阻塞模式下。這意味著不能將FileChannel與Selector一起使用绽左,因?yàn)镕ileChannel不能切換到非阻塞模式悼嫉。而套接字通道都可以。
可以監(jiān)聽四種不同類型的事件:
Connect
Accept
Read
Write
通道觸發(fā)了一個(gè)事件意思是該事件已經(jīng)就緒拼窥。所以戏蔑,某個(gè)channel成功連接到另一個(gè)服務(wù)器稱為“連接就緒”。一個(gè)server socket channel準(zhǔn)備好接收新進(jìn)入的連接稱為“接收就緒”鲁纠。一個(gè)有數(shù)據(jù)可讀的通道可以說是“讀就緒”总棵。等待寫數(shù)據(jù)的通道可以說是“寫就緒”。
這四種事件用SelectionKey的四個(gè)常量來表示:
SelectionKey.OP_CONNECT
SelectionKey.OP_ACCEPT
SelectionKey.OP_READ
SelectionKey.OP_WRITE
SelectionKey中包含
interest集合
ready集合
Channel
Selector
附加的對(duì)象(可選)
int interestSet = selectionKey.interestOps();
int readySet = selectionKey.readyOps();
selectionKey.isAcceptable();
selectionKey.isConnectable();
selectionKey.isReadable();
selectionKey.isWritable();
Channel? channel? = selectionKey.channel();
Selector selector = selectionKey.selector();
select()阻塞到至少有一個(gè)通道在你注冊(cè)的事件上就緒了房交。
select(long timeout)和select()一樣彻舰,除了最長會(huì)阻塞timeout毫秒(參數(shù))。
selectNow()不會(huì)阻塞候味,不管什么通道就緒都立刻返回(譯者注:此方法執(zhí)行非阻塞的選擇操作刃唤。如果自從前一次選擇操作后,沒有通道變成可選擇的白群,則此方法直接返回零尚胞。)。
Set selectedKeys = selector.selectedKeys();
selector.wakeUp()
Selector selector = Selector.open();
02channel.configureBlocking(false);
03SelectionKey key = channel.register(selector, SelectionKey.OP_READ);
04while(true) {
05intreadyChannels = selector.select();
06if(readyChannels ==0)continue;
07Set selectedKeys = selector.selectedKeys();
08Iterator keyIterator = selectedKeys.iterator();
09while(keyIterator.hasNext()) {
10SelectionKey key = keyIterator.next();
11if(key.isAcceptable()) {
12// a connection was accepted by a ServerSocketChannel.
13}elseif(key.isConnectable()) {
14// a connection was established with a remote server.
15}elseif(key.isReadable()) {
16// a channel is ready for reading
17}elseif(key.isWritable()) {
18// a channel is ready for writing
19}
20keyIterator.remove();
21}
22}
SocketChannel
打開一個(gè)SocketChannel并連接到互聯(lián)網(wǎng)上的某臺(tái)服務(wù)器帜慢。
一個(gè)新連接到達(dá)ServerSocketChannel時(shí)笼裳,會(huì)創(chuàng)建一個(gè)SocketChannel唯卖。
打開 SocketChannel
下面是SocketChannel的打開方式:
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));
關(guān)閉 SocketChannel
當(dāng)用完SocketChannel之后調(diào)用SocketChannel.close()關(guān)閉SocketChannel:
socketChannel.close();
打開一個(gè)SocketChannel并連接到互聯(lián)網(wǎng)上的某臺(tái)服務(wù)器。
一個(gè)新連接到達(dá)ServerSocketChannel時(shí)躬柬,會(huì)創(chuàng)建一個(gè)SocketChannel拜轨。
打開 SocketChannel
下面是SocketChannel的打開方式:
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("http://jenkov.com", 80));
關(guān)閉 SocketChannel
當(dāng)用完SocketChannel之后調(diào)用SocketChannel.close()關(guān)閉SocketChannel:
socketChannel.close();
ServerSocketChannel
Java NIO中的 ServerSocketChannel 是一個(gè)可以監(jiān)聽新進(jìn)來的TCP連接的通道, 就像標(biāo)準(zhǔn)IO中的ServerSocket一樣。ServerSocketChannel類在 java.nio.channels包中允青。
這里有個(gè)例子:
01ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
02
03serverSocketChannel.socket().bind(newInetSocketAddress(9999));
04
05while(true){
06SocketChannel socketChannel =
07serverSocketChannel.accept();
08
09//do something with socketChannel...
10}
datagramChannel
DatagramChannel channel = DatagramChannel.open();
channel.socket().bind(new InetSocketAddress(9999));
channel.connect(new InetSocketAddress("jenkov.com", 80));
pipe
Java NIO 管道是2個(gè)線程之間的單向數(shù)據(jù)連接橄碾。Pipe有一個(gè)source通道和一個(gè)sink通道。數(shù)據(jù)會(huì)被寫到sink通道颠锉,從source通道讀取法牲。
這里是Pipe原理的圖示: