NIO模式的IO多路復(fù)用底層原理

上一篇 <<<BIO模型的缺陷
下一篇 >>>select、poll、epoll的區(qū)別


產(chǎn)生緣由

因?yàn)锽IO存在線(xiàn)程阻塞,偽異步的話(huà)也會(huì)存在線(xiàn)程安全和資源浪費(fèi)情況,而NIO恰好能解決這些問(wèn)題。

底層原理關(guān)鍵詞

面向與緩沖區(qū)
基于通道實(shí)現(xiàn)非阻塞式io
多路io復(fù)用實(shí)現(xiàn)(選擇器)

通道(Channel)----TCP鏈接道路
通常我們nio所有的操作都是通過(guò)通道開(kāi)始的,所有的通道都會(huì)注冊(cè)到統(tǒng)一個(gè)選擇器(Selector)上實(shí)現(xiàn)管理,在通過(guò)選擇器將數(shù)據(jù)統(tǒng)一寫(xiě)入到 buffer中。
緩沖區(qū)(Buffer)------加快數(shù)據(jù)的讀取
Buffer本質(zhì)上就是一塊內(nèi)存區(qū),可以用來(lái)讀取數(shù)據(jù),也就先將數(shù)據(jù)寫(xiě)入到緩沖區(qū)中、在統(tǒng)一的寫(xiě)入到硬盤(pán)上。
選擇器(Selector)------通道的管理,實(shí)現(xiàn)多路IO復(fù)用機(jī)制---一個(gè)線(xiàn)程處理多個(gè)TCP請(qǐng)求。
Selector可以稱(chēng)做為選擇器,也可以把它叫做多路復(fù)用器,可以在單線(xiàn)程的情況下可以去維護(hù)多個(gè)Channel,也可以去維護(hù)多個(gè)連接;
線(xiàn)程--完成具體的業(yè)務(wù)

Nio技術(shù)多路IO復(fù)用底層實(shí)現(xiàn)原理

多路:實(shí)際指的就是多個(gè)不同的tcp連接
復(fù)用:一個(gè)線(xiàn)程可以維護(hù)多個(gè)不同的io操作
好處: 占用cpu資源非常小、保證線(xiàn)程安全問(wèn)題

手寫(xiě)偽NIO代碼

public class SocketNioTcpServer {
    private static List<SocketChannel> listSocketChannel = new ArrayList<>();
    private static ByteBuffer byteBuffer = ByteBuffer.allocate(512);

    public static void main(String[] args) {
        try {
            // 1.創(chuàng)建一個(gè)ServerSocketChannel
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            // 2. 綁定地址
            ServerSocketChannel bind = serverSocketChannel.bind(new InetSocketAddress(9090));
            serverSocketChannel.configureBlocking(false);
            while (true) {
                /**channel管道:TCP數(shù)據(jù)傳輸?shù)耐ǖ?/
                SocketChannel socketChannel = serverSocketChannel.accept();
                if (socketChannel != null) {
                    /**通道加入到選擇器中*/
                    socketChannel.configureBlocking(false);
                    listSocketChannel.add(socketChannel);
                }
                /**輪詢(xún)選擇器下的所有通道信息,利用buffer緩存機(jī)制讀取數(shù)據(jù)*/
                for (SocketChannel scl : listSocketChannel) {
                    try {
                        int read = scl.read(byteBuffer);
                        if (read > 0) {
                            byteBuffer.flip();
                            Charset charset = Charset.forName("UTF-8");
                            String receiveText = charset.newDecoder().decode
                                    (byteBuffer.asReadOnlyBuffer()).toString();
                            System.out.println(Thread.currentThread().getName()+" receiveText:" + receiveText);
                        }
                        listSocketChannel.remove(scl);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

推薦閱讀:
<<<OSI七層模型與層上協(xié)議
<<<TCP的三次握手建立鏈接和四次揮手釋放鏈接
<<<TCP、UDP及Socket代碼示例
<<<Https的1.0、2.0協(xié)議及長(zhǎng)短鏈接區(qū)別
<<<Linux系統(tǒng)的五種IO模型
<<<BIO和NIO區(qū)別
<<<BIO模型的缺陷
<<<select、poll、epoll的區(qū)別
<<<Redis為什么單線(xiàn)程能夠支持高并發(fā)
<<<Netty初識(shí)
<<<Netty的粘包和拆包問(wèn)題分析
<<<粘包和拆包問(wèn)題解決方案匯總
<<<序列化與反序列化知識(shí)點(diǎn)匯總
<<<MessagePack反序列化使用示例
<<<Marshalling在Netty中的使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容