欧美free性护士vide0shd,老熟女,一区二区三区,久久久久夜夜夜精品国产,久久久久久综合网天天,欧美成人护士h版

首頁綜合 正文
目錄

柚子快報邀請碼778899分享:網(wǎng)絡(luò) io,nio,aio區(qū)別

柚子快報邀請碼778899分享:網(wǎng)絡(luò) io,nio,aio區(qū)別

http://yzkb.51969.com/

文章目錄

前言io類型介紹同步阻塞io同步非阻塞ioio多路復(fù)用異步io

普通ioaionioChannelChannel實現(xiàn)基本的 Channel代碼 示例

BufferBuffer的基本用法Buffer的capacity,position和limitcapacitypositionlimit

Buffer的類型Buffer的分配向Buffer中寫數(shù)據(jù)從Buffer中讀取數(shù)據(jù)

Selector為什么使用Selector?Selector的創(chuàng)建向Selector注冊通道SelectionKey通過Selector選擇通道

總結(jié)

前言

說起io,大家一定十分的熟悉。因為不管是什么編程語言,都離不開io操作。不管是對本地文件的io操作,還是網(wǎng)絡(luò)的io流,在日常的程序開發(fā)中都是十分的常見。那么今天我們就詳細(xì)的介紹一下io,nio,aio的區(qū)別,讓大家對io操作有個比較深刻的理解。 UNIX 系統(tǒng)下的 I/O 模型有 5 種:同步阻塞 I/O、同步非阻塞 I/O、I/O 多路復(fù)用、信號驅(qū)動 I/O 和異步 I/O。而所謂的io,nio,aio只是他們的設(shè)計和使用的io模型不同。

io類型介紹

這里我們主要介紹java中使用到的io模型 首先我們介紹io模型之前,大家要清楚一個io操作大致流程是怎樣的。這里我們拿網(wǎng)絡(luò)io進(jìn)行舉例。當(dāng)一個網(wǎng)絡(luò)io開始的時候,將會設(shè)計到兩個對象,一個是調(diào)用io的用戶線程,還有一個是讀取數(shù)據(jù)的操作系統(tǒng)內(nèi)核,一個進(jìn)程的地址地址空間分為用戶空間和內(nèi)核空間。用戶線程不能直接訪問內(nèi)核空間。 當(dāng)用戶發(fā)起io操作的時候,會經(jīng)歷兩個步驟 1.用戶線程等待內(nèi)核從網(wǎng)卡讀取數(shù)據(jù)到內(nèi)核空間 2.內(nèi)核將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間 各個io模型的不同就是實現(xiàn)這個兩步驟方式不一樣

同步阻塞io

同步阻塞 I/O:用戶線程發(fā)起 read 調(diào)用后就阻塞了,讓出 CPU。內(nèi)核等待網(wǎng)卡數(shù)據(jù)到來,把數(shù)據(jù)從網(wǎng)卡拷貝到內(nèi)核空間,接著把數(shù)據(jù)拷貝到用戶空間,再把用戶線程叫醒。

同步非阻塞io

同步阻塞型io:用戶線程不斷的發(fā)起調(diào)用read,在數(shù)據(jù)讀取到內(nèi)核空間之前,read一直返回失敗,直到數(shù)據(jù)進(jìn)入內(nèi)核空間,才返回成功,但是在等內(nèi)核將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間的過程仍是阻塞。直到數(shù)據(jù)到了用戶空間,該線程才會從阻塞狀態(tài)喚醒。

io多路復(fù)用

io多路復(fù)用:io多路復(fù)用將讀取操作分為了兩個步驟,首先是讓select詢問數(shù)據(jù)是否準(zhǔn)備好了,數(shù)據(jù)準(zhǔn)備好了,也就是數(shù)據(jù)到了內(nèi)核空間,才開始發(fā)起read調(diào)用。在等待數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間這段時間里,線程還是阻塞的。那為什么叫 I/O 多路復(fù)用呢?因為一次 select 調(diào)用可以向內(nèi)核查多個數(shù)據(jù)通道(Channel)的狀態(tài),所以叫多路復(fù)用。

異步io

異步io:用戶再發(fā)起read調(diào)用的時候,同時注冊一個回調(diào)函數(shù),然后read立即返回,等到數(shù)據(jù)到達(dá)用戶空間之后,直接執(zhí)行回調(diào)函數(shù)即可。整個過程沒有一點阻塞。

普通io

普通io就是大家日常使用的java io,例如 inputstream等,都是普通的io,使用的時候,就會阻塞整個線程,直到數(shù)據(jù)拷貝到用戶空間為止。

aio

服務(wù)器端

import java.io.IOException;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.channels.AsynchronousServerSocketChannel;

import java.nio.channels.AsynchronousSocketChannel;

import java.nio.channels.CompletionHandler;

import java.util.concurrent.ExecutionException;

import java.util.concurrent.Future;

import java.util.concurrent.TimeUnit;

import java.util.concurrent.TimeoutException;

public class AIOEchoServer {

public final static int PORT = 8001;

public final static String IP = "127.0.0.1";

private AsynchronousServerSocketChannel server = null;

public AIOEchoServer(){

try {

//同樣是利用工廠方法產(chǎn)生一個通道,異步通道 AsynchronousServerSocketChannel

server = AsynchronousServerSocketChannel.open().bind(new InetSocketAddress(IP,PORT));

} catch (IOException e) {

e.printStackTrace();

}

}

//使用這個通道(server)來進(jìn)行客戶端的接收和處理

public void start(){

System.out.println("Server listen on "+PORT);

//注冊事件和事件完成后的處理器,這個CompletionHandler就是事件完成后的處理器

server.accept(null,new CompletionHandler(){

final ByteBuffer buffer = ByteBuffer.allocate(1024);

@Override

public void completed(AsynchronousSocketChannel result,Object attachment) {

System.out.println(Thread.currentThread().getName());

Future writeResult = null;

try{

buffer.clear();

result.read(buffer).get(100,TimeUnit.SECONDS);

System.out.println("In server: "+ new String(buffer.array()));

//將數(shù)據(jù)寫回客戶端

buffer.flip();

writeResult = result.write(buffer);

}catch(InterruptedException | ExecutionException | TimeoutException e){

e.printStackTrace();

}finally{

server.accept(null,this);

try {

writeResult.get();

result.close();

} catch (InterruptedException | ExecutionException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

}

}

@Override

public void failed(Throwable exc, Object attachment) {

System.out.println("failed:"+exc);

}

});

}

public static void main(String[] args) {

new AIOEchoServer().start();

while(true){

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

import java.io.IOException;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.channels.AsynchronousSocketChannel;

import java.nio.channels.CompletionHandler;

public class AIOClient {

public static void main(String[] args) throws IOException {

final AsynchronousSocketChannel client = AsynchronousSocketChannel.open();

InetSocketAddress serverAddress = new InetSocketAddress("127.0.0.1",8001);

CompletionHandler handler = new CompletionHandler(){

@Override

public void completed(Void result, Object attachment) {

client.write(ByteBuffer.wrap("Hello".getBytes()),null,

new CompletionHandler(){

@Override

public void completed(Integer result,

Object attachment) {

final ByteBuffer buffer = ByteBuffer.allocate(1024);

client.read(buffer,buffer,new CompletionHandler(){

@Override

public void completed(Integer result,

ByteBuffer attachment) {

buffer.flip();

System.out.println(new String(buffer.array()));

try {

client.close();

} catch (IOException e) {

e.printStackTrace();

}

}

@Override

public void failed(Throwable exc,

ByteBuffer attachment) {

}

});

}

@Override

public void failed(Throwable exc, Object attachment) {

}

});

}

@Override

public void failed(Throwable exc, Object attachment) {

}

};

client.connect(serverAddress, null, handler);

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

上面是一個簡單的aio例子,上面的代碼我們可以看出,相較于普通的io,aio多了一個回調(diào)事件,這個也是aio實現(xiàn)異步的關(guān)鍵,這個回調(diào)事件里面正是處理數(shù)據(jù)的方法。因此,aio可以不用等數(shù)據(jù)到達(dá)再執(zhí)行處理時間,而是變成數(shù)據(jù)到達(dá)后調(diào)用回調(diào)事件,自己處理自己。

nio

nio使用的應(yīng)該是io多路復(fù)用模型,其中比較重要的組件有三個,Selectors,Channels,Buffers。而nio的工作機(jī)制主要就是,selector不斷輪詢,查詢多個通道,檢測通道數(shù)據(jù)是否到達(dá),如果到達(dá)。則將該通道標(biāo)志為就緒狀態(tài),然后可以將通道數(shù)據(jù)讀取到buffer里面,然后再進(jìn)行后續(xù)操作。接下來,我們將分別介紹這三個組件

Channel

Channel實現(xiàn)

這些是Java NIO中最重要的通道的實現(xiàn):

FileChannel DatagramChannel SocketChannel ServerSocketChannel FileChannel 從文件中讀寫數(shù)據(jù)。

DatagramChannel 能通過UDP讀寫網(wǎng)絡(luò)中的數(shù)據(jù)。

SocketChannel 能通過TCP讀寫網(wǎng)絡(luò)中的數(shù)據(jù)。

ServerSocketChannel可以監(jiān)聽新進(jìn)來的TCP連接,像Web服務(wù)器那樣。對每一個新進(jìn)來的連接都會創(chuàng)建一個SocketChannel。

基本的 Channel代碼 示例

下面是一個使用FileChannel讀取數(shù)據(jù)到Buffer中的示例:

[code lang=”java”]

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");

FileChannel inChannel = aFile.getChannel();

ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buf);

while (bytesRead != -1) {

System.out.println("Read " + bytesRead);

buf.flip();

while(buf.hasRemaining()){

System.out.print((char) buf.get());

}

buf.clear();

bytesRead = inChannel.read(buf);

}

aFile.close();

[/code]

Buffer

Buffer的基本用法

使用Buffer讀寫數(shù)據(jù)一般遵循以下四個步驟:

寫入數(shù)據(jù)到Buffer 調(diào)用flip()方法 從Buffer中讀取數(shù)據(jù) 調(diào)用clear()方法或者compact()方法 當(dāng)向buffer寫入數(shù)據(jù)時,buffer會記錄下寫了多少數(shù)據(jù)。一旦要讀取數(shù)據(jù),需要通過flip()方法將Buffer從寫模式切換到讀模式。在讀模式下,可以讀取之前寫入到buffer的所有數(shù)據(jù)。

一旦讀完了所有的數(shù)據(jù),就需要清空緩沖區(qū),讓它可以再次被寫入。有兩種方式能清空緩沖區(qū):調(diào)用clear()或compact()方法。clear()方法會清空整個緩沖區(qū)。compact()方法只會清除已經(jīng)讀過的數(shù)據(jù)。任何未讀的數(shù)據(jù)都被移到緩沖區(qū)的起始處,新寫入的數(shù)據(jù)將放到緩沖區(qū)未讀數(shù)據(jù)的后面。

下面是一個使用Buffer的例子:

[code lang=”java”]

RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");

FileChannel inChannel = aFile.getChannel();

//create buffer with capacity of 48 bytes

ByteBuffer buf = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buf); //read into buffer.

while (bytesRead != -1) {

buf.flip(); //make buffer ready for read

while(buf.hasRemaining()){

System.out.print((char) buf.get()); // read 1 byte at a time

}

buf.clear(); //make buffer ready for writing

bytesRead = inChannel.read(buf);

}

aFile.close();

[/code]

Buffer的capacity,position和limit

緩沖區(qū)本質(zhì)上是一塊可以寫入數(shù)據(jù),然后可以從中讀取數(shù)據(jù)的內(nèi)存。這塊內(nèi)存被包裝成NIO Buffer對象,并提供了一組方法,用來方便的訪問該塊內(nèi)存。

為了理解Buffer的工作原理,需要熟悉它的三個屬性:

capacity position limit position和limit的含義取決于Buffer處在讀模式還是寫模式。不管Buffer處在什么模式,capacity的含義總是一樣的。

這里有一個關(guān)于capacity,position和limit在讀寫模式中的說明,詳細(xì)的解釋在插圖后面。

capacity

作為一個內(nèi)存塊,Buffer有一個固定的大小值,也叫“capacity”.你只能往里寫capacity個byte、long,char等類型。一旦Buffer滿了,需要將其清空(通過讀數(shù)據(jù)或者清除數(shù)據(jù))才能繼續(xù)寫數(shù)據(jù)往里寫數(shù)據(jù)。

position

當(dāng)你寫數(shù)據(jù)到Buffer中時,position表示當(dāng)前的位置。初始的position值為0.當(dāng)一個byte、long等數(shù)據(jù)寫到Buffer后, position會向前移動到下一個可插入數(shù)據(jù)的Buffer單元。position最大可為capacity – 1.

當(dāng)讀取數(shù)據(jù)時,也是從某個特定位置讀。當(dāng)將Buffer從寫模式切換到讀模式,position會被重置為0. 當(dāng)從Buffer的position處讀取數(shù)據(jù)時,position向前移動到下一個可讀的位置。

limit

在寫模式下,Buffer的limit表示你最多能往Buffer里寫多少數(shù)據(jù)。 寫模式下,limit等于Buffer的capacity。

當(dāng)切換Buffer到讀模式時, limit表示你最多能讀到多少數(shù)據(jù)。因此,當(dāng)切換Buffer到讀模式時,limit會被設(shè)置成寫模式下的position值。換句話說,你能讀到之前寫入的所有數(shù)據(jù)(limit被設(shè)置成已寫數(shù)據(jù)的數(shù)量,這個值在寫模式下就是position)

Buffer的類型

Java NIO 有以下Buffer類型

ByteBuffer MappedByteBuffer CharBuffer DoubleBuffer FloatBuffer IntBuffer LongBuffer ShortBuffer p<> 如你所見,這些Buffer類型代表了不同的數(shù)據(jù)類型。換句話說,就是可以通過char,short,int,long,float 或 double類型來操作緩沖區(qū)中的字節(jié)。

MappedByteBuffer 有些特別,在涉及它的專門章節(jié)中再講。

Buffer的分配

要想獲得一個Buffer對象首先要進(jìn)行分配。 每一個Buffer類都有一個allocate方法。下面是一個分配48字節(jié)capacity的ByteBuffer的例子。

[code lang=”java”]

ByteBuffer buf = ByteBuffer.allocate(48);

[/code]

這是分配一個可存儲1024個字符的CharBuffer:

[code lang=”java”]

CharBuffer buf = CharBuffer.allocate(1024);

[/code]

向Buffer中寫數(shù)據(jù)

寫數(shù)據(jù)到Buffer有兩種方式:

從Channel寫到Buffer。 通過Buffer的put()方法寫到Buffer里。 從Channel寫到Buffer的例子

[code lang=”java”]

int bytesRead = inChannel.read(buf); //read into buffer.

[/code]

通過put方法寫B(tài)uffer的例子:

[code lang=”java”]

buf.put(127);

[/code]

put方法有很多版本,允許你以不同的方式把數(shù)據(jù)寫入到Buffer中。例如, 寫到一個指定的位置,或者把一個字節(jié)數(shù)組寫入到Buffer。 更多Buffer實現(xiàn)的細(xì)節(jié)參考JavaDoc。

flip()方法 flip方法將Buffer從寫模式切換到讀模式。調(diào)用flip()方法會將position設(shè)回0,并將limit設(shè)置成之前position的值。

換句話說,position現(xiàn)在用于標(biāo)記讀的位置,limit表示之前寫進(jìn)了多少個byte、char等 —— 現(xiàn)在能讀取多少個byte、char等。

從Buffer中讀取數(shù)據(jù)

從Buffer中讀取數(shù)據(jù)有兩種方式:

1.從Buffer讀取數(shù)據(jù)到Channel。 2.使用get()方法從Buffer中讀取數(shù)據(jù)。 從Buffer讀取數(shù)據(jù)到Channel的例子:

[code lang=”java”]

//read from buffer into channel.

int bytesWritten = inChannel.write(buf);

[/code]

使用get()方法從Buffer中讀取數(shù)據(jù)的例子

[code lang=”java”]

byte aByte = buf.get();

[/code]

get方法有很多版本,允許你以不同的方式從Buffer中讀取數(shù)據(jù)。例如,從指定position讀取,或者從Buffer中讀取數(shù)據(jù)到字節(jié)數(shù)組。更多Buffer實現(xiàn)的細(xì)節(jié)參考JavaDoc。

Selector

為什么使用Selector?

僅用單個線程來處理多個Channels的好處是,只需要更少的線程來處理通道。事實上,可以只用一個線程處理所有的通道。對于操作系統(tǒng)來說,線程之間上下文切換的開銷很大,而且每個線程都要占用系統(tǒng)的一些資源(如內(nèi)存)。因此,使用的線程越少越好。

但是,需要記住,現(xiàn)代的操作系統(tǒng)和CPU在多任務(wù)方面表現(xiàn)的越來越好,所以多線程的開銷隨著時間的推移,變得越來越小了。實際上,如果一個CPU有多個內(nèi)核,不使用多任務(wù)可能是在浪費CPU能力。不管怎么說,關(guān)于那種設(shè)計的討論應(yīng)該放在另一篇不同的文章中。在這里,只要知道使用Selector能夠處理多個通道就足夠了。

Selector的創(chuàng)建

通過調(diào)用Selector.open()方法創(chuàng)建一個Selector,如下:

[code lang=”java”] Selector selector = Selector.open(); [/code]

向Selector注冊通道

為了將Channel和Selector配合使用,必須將channel注冊到selector上。通過SelectableChannel.register()方法來實現(xiàn),如下:

[code lang=”java”]

channel.configureBlocking(false);

SelectionKey key = channel.register(selector,

Selectionkey.OP_READ);

[/code]

與Selector一起使用時,Channel必須處于非阻塞模式下。這意味著不能將FileChannel與Selector一起使用,因為FileChannel不能切換到非阻塞模式。而套接字通道都可以。

注意register()方法的第二個參數(shù)。這是一個“interest集合”,意思是在通過Selector監(jiān)聽Channel時對什么事件感興趣。可以監(jiān)聽四種不同類型的事件:

1.Connect 2.Accept 3.Read 4.Write 通道觸發(fā)了一個事件意思是該事件已經(jīng)就緒。所以,某個channel成功連接到另一個服務(wù)器稱為“連接就緒”。一個server socket channel準(zhǔn)備好接收新進(jìn)入的連接稱為“接收就緒”。一個有數(shù)據(jù)可讀的通道可以說是“讀就緒”。等待寫數(shù)據(jù)的通道可以說是“寫就緒”。

這四種事件用SelectionKey的四個常量來表示:

1.SelectionKey.OP_CONNECT 2.SelectionKey.OP_ACCEPT 3.SelectionKey.OP_READ 4.SelectionKey.OP_WRITE 如果你對不止一種事件感興趣,那么可以用“位或”操作符將常量連接起來,如下:

[code lang=”java”] int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE; [/code]

在下面還會繼續(xù)提到interest集合。

SelectionKey

在上一小節(jié)中,當(dāng)向Selector注冊Channel時,register()方法會返回一個SelectionKey對象。這個對象包含了一些你感興趣的屬性:

interest集合 ready集合 Channel Selector 附加的對象(可選) 下面我會描述這些屬性。

interest集合 就像向Selector注冊通道一節(jié)中所描述的,interest集合是你所選擇的感興趣的事件集合??梢酝ㄟ^SelectionKey讀寫interest集合,像這樣:

[code lang=”java”] int interestSet = selectionKey.interestOps();

boolean isInterestedInAccept = (interestSet & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT; boolean isInterestedInConnect = interestSet & SelectionKey.OP_CONNECT; boolean isInterestedInRead = interestSet & SelectionKey.OP_READ; boolean isInterestedInWrite = interestSet & SelectionKey.OP_WRITE; [/code]

可以看到,用“位與”操作interest 集合和給定的SelectionKey常量,可以確定某個確定的事件是否在interest 集合中。

ready集合 ready 集合是通道已經(jīng)準(zhǔn)備就緒的操作的集合。在一次選擇(Selection)之后,你會首先訪問這個ready set。Selection將在下一小節(jié)進(jìn)行解釋??梢赃@樣訪問ready集合:

[code lang=”java”] int readySet = selectionKey.readyOps(); [/code]

可以用像檢測interest集合那樣的方法,來檢測channel中什么事件或操作已經(jīng)就緒。但是,也可以使用以下四個方法,它們都會返回一個布爾類型:

[code lang=”java”] selectionKey.isAcceptable(); selectionKey.isConnectable(); selectionKey.isReadable(); selectionKey.isWritable(); [/code]

Channel + Selector 從SelectionKey訪問Channel和Selector很簡單。如下:

[code lang=”java”] Channel channel = selectionKey.channel(); Selector selector = selectionKey.selector(); [/code]

附加的對象 可以將一個對象或者更多信息附著到SelectionKey上,這樣就能方便的識別某個給定的通道。例如,可以附加 與通道一起使用的Buffer,或是包含聚集數(shù)據(jù)的某個對象。使用方法如下:

[code lang=”java”] selectionKey.attach(theObject); Object attachedObj = selectionKey.attachment(); [/code]

還可以在用register()方法向Selector注冊Channel的時候附加對象。如:

[code lang=”java”] SelectionKey key = channel.register(selector, SelectionKey.OP_READ, theObject); [/code]

通過Selector選擇通道

一旦向Selector注冊了一或多個通道,就可以調(diào)用幾個重載的select()方法。這些方法返回你所感興趣的事件(如連接、接受、讀或?qū)懀┮呀?jīng)準(zhǔn)備就緒的那些通道。換句話說,如果你對“讀就緒”的通道感興趣,select()方法會返回讀事件已經(jīng)就緒的那些通道。

下面是select()方法:

int select() int select(long timeout) int selectNow() select()阻塞到至少有一個通道在你注冊的事件上就緒了。

select(long timeout)和select()一樣,除了最長會阻塞timeout毫秒(參數(shù))。

selectNow()不會阻塞,不管什么通道就緒都立刻返回(譯者注:此方法執(zhí)行非阻塞的選擇操作。如果自從前一次選擇操作后,沒有通道變成可選擇的,則此方法直接返回零。)。

select()方法返回的int值表示有多少通道已經(jīng)就緒。亦即,自上次調(diào)用select()方法后有多少通道變成就緒狀態(tài)。如果調(diào)用select()方法,因為有一個通道變成就緒狀態(tài),返回了1,若再次調(diào)用select()方法,如果另一個通道就緒了,它會再次返回1。如果對第一個就緒的channel沒有做任何操作,現(xiàn)在就有兩個就緒的通道,但在每次select()方法調(diào)用之間,只有一個通道就緒了。

selectedKeys() 一旦調(diào)用了select()方法,并且返回值表明有一個或更多個通道就緒了,然后可以通過調(diào)用selector的selectedKeys()方法,訪問“已選擇鍵集(selected key set)”中的就緒通道。如下所示:

[code lang=”java”] Set selectedKeys = selector.selectedKeys(); [/code]

當(dāng)像Selector注冊Channel時,Channel.register()方法會返回一個SelectionKey 對象。這個對象代表了注冊到該Selector的通道。可以通過SelectionKey的selectedKeySet()方法訪問這些對象。

可以遍歷這個已選擇的鍵集合來訪問就緒的通道。如下:

[code lang=”java”]

Set selectedKeys = selector.selectedKeys();

Iterator keyIterator = selectedKeys.iterator();

while(keyIterator.hasNext()) {

SelectionKey key = keyIterator.next();

if(key.isAcceptable()) {

// a connection was accepted by a ServerSocketChannel.

} else if (key.isConnectable()) {

// a connection was established with a remote server.

} else if (key.isReadable()) {

// a channel is ready for reading

} else if (key.isWritable()) {

// a channel is ready for writing

}

keyIterator.remove();

}

[/code]

這個循環(huán)遍歷已選擇鍵集中的每個鍵,并檢測各個鍵所對應(yīng)的通道的就緒事件。

注意每次迭代末尾的keyIterator.remove()調(diào)用。Selector不會自己從已選擇鍵集中移除SelectionKey實例。必須在處理完通道時自己移除。下次該通道變成就緒時,Selector會再次將其放入已選擇鍵集中。

SelectionKey.channel()方法返回的通道需要轉(zhuǎn)型成你要處理的類型,如ServerSocketChannel或SocketChannel等。

總結(jié)

我們首先介紹了io的五種模型,然后在此基礎(chǔ)上又介紹了io,nio,aio的區(qū)別和其所使用的模型。但是這個有一點,我們介紹的是nio1.0的版本,2.0版本可能不太一樣,有需要的可以自行前往官網(wǎng)了解學(xué)習(xí)。最后希望通過本篇文章,大家可以對不同的io有一個清晰的認(rèn)知。

柚子快報邀請碼778899分享:網(wǎng)絡(luò) io,nio,aio區(qū)別

http://yzkb.51969.com/

參考閱讀

評論可見,查看隱藏內(nèi)容

本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。

轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。

本文鏈接:http://gantiao.com.cn/post/19472755.html

發(fā)布評論

您暫未設(shè)置收款碼

請在主題配置——文章設(shè)置里上傳

掃描二維碼手機(jī)訪問

文章目錄