最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

小白也可以學(xué)會的Java NIO的Write事件

 更新時(shí)間:2021年06月01日 14:17:11   作者:JavaEdge.  
剛開始對NIO的寫操作理解的不深,不知道為什么要注冊寫事件,何時(shí)注冊寫事件,為什么寫完之后要取消注冊寫事件,今天特地整理了本篇文章,需要的朋友可以參考下

一、NIO Server端

1.1 多路復(fù)用開發(fā)一般步驟

//打開選擇器
Selector selector = Selector.open();
//打開通到
ServerSocketChannel socketChannel = ServerSocketChannel.open();
//配置非阻塞模型
socketChannel.configureBlocking(false);
//綁定端口
socketChannel.bind(new InetSocketAddress(8080));
//注冊事件,OP_ACCEPT只適用于ServerSocketChannel 
socketChannel.register(selector, SelectionKey.OP_ACCEPT);
while (true) {
    selector.select();
    Set<SelectionKey> selectionKeys = selector.selectedKeys();
    Iterator<SelectionKey> iter = selectionKeys.iterator();
    while(iter.hasNext()) {
        SelectionKey key = iter.next();
        if(key.isAcceptable()) {
            SocketChannel channel = ((ServerSocketChannel)key.channel()).accept();
            channel.configureBlocking(false);
            channel.register(selector,SelectionKey.OP_READ);
        }
        
        if(key.isWritable()) {
        }
        
        if(key.isReadable()) {
            SocketChannel channel = (SocketChannel) key.channel();
            ByteBuffer readBuffer = ByteBuffer.allocate(1024);
            channel.read(readBuffer);
            readBuffer.flip();
            // handler Buffer
            // 一般是響應(yīng)客戶端的數(shù)據(jù)
            // 直接是write寫不就完事了嘛,為啥需要write事件?
            // channel.write(...)
        }
        iter.remove();
    }
}

1.2 解惑寫事件

對NIO的寫操作:

  • 為什么要注冊寫事件
  • 何時(shí)注冊寫事件
  • 為什么寫完之后要取消注冊寫事件

如果有channel在Selector上注冊了SelectionKey.OP_WRITE,在調(diào)用selector.select();時(shí),系統(tǒng)會檢查內(nèi)核寫緩沖區(qū)是否可寫:

  • 如果可寫,selector.select();立即返回,進(jìn)入key.isWritable()
  • 何時(shí)不可寫?比如緩沖區(qū)已滿,channel調(diào)用了shutdownOutPut等

當(dāng)然除了注冊寫事件,你也可以在channel直接調(diào)用write(…),也可以將數(shù)據(jù)發(fā)出去,但這樣不夠靈活,而且可能浪費(fèi)CPU。

比如服務(wù)端需要發(fā)送一個200M的Buffer,看看是否使用OP_WRITE事件的區(qū)別。

二、不使用事件

程序運(yùn)行到這會等到200M文件發(fā)送完成后才繼續(xù)往下執(zhí)行,不符合異步事件模型的思想。若緩沖區(qū)一直處不可寫狀態(tài),則該過程一直在這里死循環(huán),浪費(fèi)CPU。

// 200M的Buffer
ByteBuffer buffer = .... 

while(buffer.hasRemaining()) {
    // 該方法只會寫入小于socket's output buffer空閑區(qū)域的任何字節(jié)數(shù)
    // 并返回寫入的字節(jié)數(shù),可能是0字節(jié)
    channel.write(buffer);
}

三、使用事件

if(key.isReadable()) {
	// 200M Buffer
    ByteBuffer buffer = .... 
    // 注冊寫事件
    key.interestOps(key.interestOps() | SelectionKey.OP_WRITE);
    // 綁定Buffer
    key.attach(buffer);
}
// 可寫分支
if(key.isWritable()) {
    ByteBuffer buffer = (ByteBuffer) key.attachment();
    SocketChannel channel = (SocketChannel) key.channel();
    if (buffer.hasRemaining()) {
        channel.write(buffer)
    } else {
        // 發(fā)送完了就取消寫事件,否則下次還會進(jìn)入寫事件分支(因?yàn)橹灰€可寫,就會進(jìn)入)
        key.interestOps(key.interestOps() & ~SelectionKey.OP_WRITE);
    }
}

要觸發(fā)寫事件,需要先向 selector 注冊該通道的寫事件,跟注冊讀事件一樣,當(dāng)?shù)讓訉懢彌_區(qū)有空閑就會觸發(fā)寫事件了,而一般來說底層的寫緩沖區(qū)大部分都是空閑的。所以一般只要注冊了寫事件,就會立馬觸發(fā)了,為了避免 cpu 空轉(zhuǎn),在寫操作完成后需要把寫事件取消掉,然后下次再有寫操作時(shí)重新注冊寫事件。

四、NIO Client端

開發(fā)的一般步驟

// 打開選擇器
Selector selector = Selector.open();
// 打開通道
SocketChannel socketChannel = SocketChannel.open();
// 配置非阻塞模型
socketChannel.configureBlocking(false);
// 連接Server
socketChannel.connect(new InetSocketAddress("127.0.0.1",8080));
// 注冊事件
socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ);
// 循環(huán)處理
while (true) {
    selector.select();
    Set<SelectionKey> keys = selector.selectedKeys();
    Iterator<SelectionKey> iter = keys.iterator();
    while(iter.hasNext()) {
        SelectionKey key = iter.next();
        if(key.isConnectable()) {
            // 連接建立或者連接建立不成功
            SocketChannel channel = (SocketChannel) key.channel();
            // 完成連接建立
            if(channel.finishConnect()) {
                
            }
        }
        
        if(key.isReadable()) {
            SocketChannel channel = (SocketChannel) key.channel();
            ByteBuffer buffer = ByteBuffer.allocate(500 * 1024 * 1024);
            buffer.clear();
            channel.read(buffer);
            // buffer Handler
        }
        iter.remove();
    }
}

起初對OP_CONNECT事件還有finishConnect不理解,OP_CONNECT事件何時(shí)觸發(fā),特別是為什么要在key.isConnectable()分支里調(diào)用finishConnect方法后才能進(jìn)行讀寫操作。

首先,在non-blocking模式下調(diào)用socketChannel.connect(new InetSocketAddress(“127.0.0.1”,8080));連接遠(yuǎn)程主機(jī),如果連接能立即建立就像本地連接一樣,該方法會立即返回true,否則該方法會立即返回false,然后系統(tǒng)底層進(jìn)行三次握手建立連接。連接有兩種結(jié)果,一種是成功連接,第二種是異常,但是connect方法已經(jīng)返回,無法通過該方法的返回值或者是異常來通知用戶程序建立連接的情況,所以由OP_CONNECT事件和finishConnect方法來通知用戶程序。不管系統(tǒng)底層三次連接是否成功,selector都會被喚醒繼而觸發(fā)OP_CONNECT事件,如果握手成功,并且該連接未被其他線程關(guān)閉,finishConnect會返回true,然后就可以順利的進(jìn)行channle讀寫。如果網(wǎng)絡(luò)故障,或者遠(yuǎn)程主機(jī)故障,握手不成功,用戶程序可以通過finishConnect方法獲得底層的異常通知,進(jìn)而處理異常。

到此這篇關(guān)于小白也可以學(xué)會的Java NIO的Write事件的文章就介紹到這了,更多相關(guān)Java NIO的Write事件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • java獲取ip地址示例

    java獲取ip地址示例

    在JSP里,獲取客戶端的IP地址的方法是:request.getRemoteAddr(),這種方法在大部分情況下都是有效的。但是在通過了Apache,Squid等反向代理軟件就不能獲取到客戶端的真實(shí)IP地址了
    2014-04-04
  • Springboot 如何實(shí)現(xiàn)filter攔截token驗(yàn)證和跨域

    Springboot 如何實(shí)現(xiàn)filter攔截token驗(yàn)證和跨域

    這篇文章主要介紹了Springboot 如何實(shí)現(xiàn)filter攔截token驗(yàn)證和跨域操作,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • Java 加密解密基礎(chǔ)分類及模式歸納整理

    Java 加密解密基礎(chǔ)分類及模式歸納整理

    這篇文章主要介紹了Java加密解密基礎(chǔ)分類方法匯總的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • java中rss解析器(rome.jar和jdom.jar)示例

    java中rss解析器(rome.jar和jdom.jar)示例

    這篇文章主要介紹了java中rss解析器(rome.jar和jdom.jar)示例,需要的朋友可以參考下
    2014-03-03
  • 淺談導(dǎo)入JavaWeb 項(xiàng)目出現(xiàn)的問題

    淺談導(dǎo)入JavaWeb 項(xiàng)目出現(xiàn)的問題

    這篇文章主要介紹了導(dǎo)入JavaWeb 項(xiàng)目出現(xiàn)的問題,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • 使用Autowired為什么會被IDEA警告最佳修改方法

    使用Autowired為什么會被IDEA警告最佳修改方法

    這篇文章主要介紹了使用Autowired為什么會被IDEA警告,應(yīng)該怎么修改最佳,除了使用@Autowired以外,我們其實(shí)也有幾種好用的方式,使用@Resource替代@Autiwired方法是其中一種,只需要改變一個注解,這里就不展示了,需要的朋友可以參考下
    2023-02-02
  • 在X分鐘內(nèi)學(xué)會C#的入門簡明教程

    在X分鐘內(nèi)學(xué)會C#的入門簡明教程

    C#是一個優(yōu)雅的、類型安全的面向?qū)ο笳Z言。使用C#,開發(fā)者可以在.NET框架下構(gòu)建安全而強(qiáng)大的應(yīng)用程序,閱讀本文可以快速的入門C#編程語言,需要的朋友可以參考下
    2014-03-03
  • Java中fail-fast和fail-safe的使用

    Java中fail-fast和fail-safe的使用

    fail-fast和fail-safe是兩種不同的迭代器行為,特別是在遍歷集合時(shí)遇到并發(fā)修改的情況,本文主要介紹了Java中fail-fast和fail-safe的使用,感興趣的可以了解一下
    2024-08-08
  • java中幾種常見的排序算法總結(jié)

    java中幾種常見的排序算法總結(jié)

    大家好,本篇文章主要講的是java中幾種常見的排序算法總結(jié),感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-01-01
  • Java中基于Shiro,JWT實(shí)現(xiàn)微信小程序登錄完整例子及實(shí)現(xiàn)過程

    Java中基于Shiro,JWT實(shí)現(xiàn)微信小程序登錄完整例子及實(shí)現(xiàn)過程

    這篇文章主要介紹了Java中基于Shiro,JWT實(shí)現(xiàn)微信小程序登錄完整例子 ,實(shí)現(xiàn)了小程序的自定義登陸,將自定義登陸態(tài)token返回給小程序作為登陸憑證。需要的朋友可以參考下
    2018-11-11

最新評論

青阳县| 泉州市| 华阴市| 普宁市| 常德市| 安多县| 墨玉县| 包头市| 荣成市| 娄底市| 类乌齐县| 长子县| 青田县| 五台县| 朝阳区| 莫力| 绩溪县| 连南| 孙吴县| 苏尼特左旗| 临泉县| 淮滨县| 湛江市| 尉犁县| 南平市| 凉山| 望奎县| 镇安县| 广平县| 阿拉善左旗| 天柱县| 湖口县| 台山市| 通州区| 临泉县| 自贡市| 高邑县| 英山县| 绥阳县| 黄大仙区| 哈密市|