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

Netty學習之理解selector原理示例

 更新時間:2023年07月13日 11:10:53   作者:pq217  
這篇文章主要為大家介紹了Netty學習之理解selector原理示例使用分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪<BR>

BIO的弊端

BIO既是Blocking IO,也叫同步阻塞模型,BIO模型如下

如果所示,多個客戶端連接一個服務端, 每出現(xiàn)一個客戶端就開一個handler(一般對應一個線程)處理

對應的服務端代碼如下

public class BioServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(9000);
        // 任務處理線程池
        ExecutorService pool = Executors.newFixedThreadPool(10);
        while (true) {
            System.out.println("server start");
            //阻塞方法等待客戶端連接
            Socket clientSocket = serverSocket.accept();
            System.out.println("new client");
            pool.execute(()->{
                handler(clientSocket);
            });
        }
    }
    private static void handler(Socket clientSocket) {
        try {
            byte[] bytes = new byte[1024];
            System.out.println("reading");
            //接收客戶端的數(shù)據(jù),阻塞方法,沒有數(shù)據(jù)可讀時就阻塞
            int read = clientSocket.getInputStream().read(bytes);
            System.out.println("read over");
            if (read != -1) {
                System.out.println("received data:" + new String(bytes, 0, read));
            }
            clientSocket.getOutputStream().write("HelloClient".getBytes());
            clientSocket.getOutputStream().flush();
        } catch (Exception e) {
        }
    }
}

上面的代碼使用了線程池來處理客戶端業(yè)務,整個代碼有兩步阻塞

  • 一步主線程阻塞等待客戶端連接
  • 一步線程池的線程阻塞等待客戶端傳輸數(shù)據(jù)準備好

其實第一步阻塞到?jīng)]什么,作為一個服務沒有客戶的情況下不阻塞也無事可做,主要是第二個阻塞,上面代碼線程池size是10,假如當前有10個客戶端連接都不發(fā)送數(shù)據(jù),那么10個線程都阻塞,此時再來一個客戶端發(fā)送完數(shù)據(jù)也無法及時處理

假設現(xiàn)在有個澡堂子,一共雇傭10個搓澡工,BIO就好比來一個客人就分配一個搓澡師傅,這個師傅就死死盯著客人洗澡,啥時候洗澡完了就開始安排搓澡,如果十個客戶在池子里洗澡洗不完,這時有11號客戶來了,沒有空閑的搓澡師傅(都在等待客戶洗完澡),那這個客戶只能傻傻的等著,實際上十個搓澡工都沒有實際干活,但卻處于傻傻的等待不可用狀態(tài)

解決思路

通過上面的例子可以看出,BIO的模型明顯是反人類的,合理的工作流程是這樣

10個搓澡師傅都待著,什么時候有人洗完澡了才分配搓澡師傅進行搓澡,這樣搓澡師傅的工作更加合理,充分的壓榨了搓澡師傅

客戶只會因為搓澡師傅都在搓澡而等待,而不是因為搓澡師傅都在傻等而等待

這樣設計顯然更加合理,也更加符合現(xiàn)實的工作流程,相當于事件驅動,當發(fā)生洗完澡(接收到數(shù)據(jù))事件后,再安排搓澡工(線程)進行處理

回到代碼怎么才能做到以事件驅動吶?更確切的說,作為java代碼,如何得知數(shù)據(jù)傳輸?shù)氖录l(fā)生吶?

顯然java本身肯定是做不到的,我們可以想一下數(shù)據(jù)的來源,一個網(wǎng)絡數(shù)據(jù)的傳輸,一臺機器通過網(wǎng)線或無線等形式發(fā)送二進制數(shù)據(jù)到一臺電腦,硬件的驅動必然能感知到,那么操作系統(tǒng)也一定能感知到,所以一個鏈接是否有數(shù)據(jù)傳輸,操作系統(tǒng)最知道!

epoll

linux 提供了epoll系列函數(shù)

上層代碼可以通過調用該系列函數(shù)訂閱感興趣的事件,后續(xù)即可感知到注冊事件的發(fā)生,主要方法如下

  • epoll_create: 創(chuàng)建一個epoll實例
  • epoll_ctl: 訂閱事件
  • epoll_wait: 阻塞等待訂閱事件的發(fā)生

有個這系列函數(shù),java代碼就可以:

  • 調用epoll_create創(chuàng)建一個epoll實例
  • 調用epoll_ctl訂閱可讀事件(相當于有數(shù)據(jù)傳輸事件)
  • 調用epoll_wait阻塞并等待時間發(fā)生

當然不能直接調用,而是調用底層C++再調用linux函數(shù)

NIO

有了操作系統(tǒng)的支持,java就可以實現(xiàn)一個不阻塞的IO服務,這就是NIO模型(Non Blocking IO)

JDK1.4開始引入java.nio包,在linux系統(tǒng)中底層就是使用epoll實現(xiàn)的(windows中基于winsock2,不開源)

先看一下NIO實現(xiàn)服務的代碼

public class NioServer {
    public static void main(String[] args) throws IOException, InterruptedException {
        // 創(chuàng)建NIO ServerSocketChannel
        ServerSocketChannel serverSocket = ServerSocketChannel.open();
        serverSocket.socket().bind(new InetSocketAddress(9000));
        serverSocket.configureBlocking(false);
        // 打開Selector處理Channel,底層調用epoll_create
        Selector selector = Selector.open();
        // 把ServerSocketChannel注冊到selector上,并且selector對客戶端accept連接操作感興趣,底層調用epoll_ctl
        serverSocket.register(selector, SelectionKey.OP_ACCEPT);
        System.out.println("服務啟動成功");
        while (true) {
            // 阻塞等待需要處理的事件發(fā)生,即調用epoll_wait
            selector.select();
            // 獲取selector中注冊的全部事件的 SelectionKey 實例
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            // 遍歷SelectionKey對事件進行處理
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();
                // 如果是OP_ACCEPT事件,則進行連接獲取和事件注冊
                if (key.isAcceptable()) {
                    ServerSocketChannel server = (ServerSocketChannel) key.channel();
                    SocketChannel socketChannel = server.accept();
                    socketChannel.configureBlocking(false);
                    // 這里只注冊了讀事件,如果需要給客戶端發(fā)送數(shù)據(jù)可以注冊寫事件,底層調用epoll_ctl
                    socketChannel.register(selector, SelectionKey.OP_READ);
                    System.out.println("客戶端連接成功");
                } else if (key.isReadable()) {  // 如果是OP_READ事件,則進行讀取和打印
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    ByteBuffer byteBuffer = ByteBuffer.allocate(128);
                    int len = socketChannel.read(byteBuffer);
                    // 如果有數(shù)據(jù),把數(shù)據(jù)打印出來
                    if (len > 0) {
                        System.out.println("接收到消息:" + new String(byteBuffer.array()));
                    } else if (len == -1) { // 如果客戶端斷開連接,關閉Socket
                        System.out.println("客戶端斷開連接");
                        socketChannel.close();
                    }
                }
                //從事件集合里刪除本次處理的key,防止下次select重復處理
                iterator.remove();
            }
        }
    }
}

上面及是一個典型的NIO代碼,其中(liunx中):

  • Selector.open() 底層調用liunx的epoll_create
  • socketChannel.register(selector, SelectionKey.OP_READ)相當于調用liunx的epoll_ctl(實際上只是緩存起來,下一步再真正執(zhí)行epoll_ctl)
  • selector.select() 底層調用epoll_wait,阻塞并等待訂閱事件發(fā)生

總結

selector 是java.nio包中一個nio解決方案,主要可以實現(xiàn)

  • 訂閱IO事件,如連接事件和有數(shù)據(jù)傳輸事件
  • 阻塞并等待任何訂閱事件的發(fā)生

在linux內(nèi)核中,selector就是對epoll函數(shù)的一種封裝,或者說epoll是linux針對java selector的實現(xiàn)

以上就是Netty學習之理解selector原理示例的詳細內(nèi)容,更多關于Netty selector原理的資料請關注腳本之家其它相關文章!

相關文章

  • SpringBoot隨機端口啟動的實現(xiàn)

    SpringBoot隨機端口啟動的實現(xiàn)

    本文主要介紹了SpringBoot隨機端口啟動的實現(xiàn),文中通過示例代碼介紹的非常詳細,需要的朋友們下面隨著小編來一起學習學習吧
    2021-07-07
  • java簡明例舉講解泛型

    java簡明例舉講解泛型

    這篇文章主要介紹了Java的泛型,針對利用繼承來實現(xiàn)通用程序設計所產(chǎn)生的問題,泛型提供了更好的解決方案,需要的朋友可以參考一下
    2022-04-04
  • Java swing讀取txt文件實現(xiàn)學生考試系統(tǒng)

    Java swing讀取txt文件實現(xiàn)學生考試系統(tǒng)

    這篇文章主要為大家詳細介紹了Java swing讀取txt文件實現(xiàn)學生考試系統(tǒng),文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-06-06
  • Spring工程中集成多個redis數(shù)據(jù)源的思路詳解

    Spring工程中集成多個redis數(shù)據(jù)源的思路詳解

    Spring項目集成雙Redis數(shù)據(jù)源需配置兩個連接工廠與RedisTemplate,通過@Primary指定默認Bean,@Qualifier注入特定Bean,支持集群環(huán)境,本文給大家介紹Spring工程中集成多個redis數(shù)據(jù)源的相關知識,感興趣的朋友一起看看吧
    2025-07-07
  • IDEA2020.2.3中創(chuàng)建JavaWeb工程的完整步驟記錄

    IDEA2020.2.3中創(chuàng)建JavaWeb工程的完整步驟記錄

    這篇文章主要給大家介紹了關于IDEA2020.2.3中創(chuàng)建JavaWeb工程的完整步驟,文中通過圖文介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • Java校驗銀行卡是否正確的核心代碼

    Java校驗銀行卡是否正確的核心代碼

    這篇文章主要介紹了Java校驗銀行卡是否正確的核心代碼,需要的朋友可以參考下
    2017-01-01
  • springboot?集成easy-captcha實現(xiàn)圖像驗證碼顯示和登錄

    springboot?集成easy-captcha實現(xiàn)圖像驗證碼顯示和登錄

    本文主要介紹了springboot?集成easy-captcha實現(xiàn)圖像驗證碼顯示和登錄,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • Springboot通過圖片路徑形式獲取圖片

    Springboot通過圖片路徑形式獲取圖片

    這篇文章主要介紹了Springboot通過圖片路徑形式獲取圖片,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • Java8使用lambda實現(xiàn)Java的尾遞歸

    Java8使用lambda實現(xiàn)Java的尾遞歸

    這篇文章主要介紹了Java8使用lambda實現(xiàn)Java的尾遞歸的相關資料,需要的朋友可以參考下
    2017-10-10
  • 如何用Java模擬XN*2圖靈機

    如何用Java模擬XN*2圖靈機

    這篇文章主要介紹了如何用Java模擬XN*2圖靈機方法,感興趣的朋友可以參考下
    2021-04-04

最新評論

霍城县| 宁河县| 灵石县| 屏南县| 大丰市| 阳城县| 聂荣县| 大渡口区| 万年县| 丰镇市| 平江县| 招远市| 拉孜县| 石阡县| 阿克| 冕宁县| 融水| 潮州市| 余姚市| 彰化市| 延津县| 西盟| 广南县| 新宁县| 古田县| 昭平县| 甘谷县| 襄汾县| 大同市| 固阳县| 久治县| 门源| 海口市| 彭山县| 渭源县| 红原县| 信丰县| 惠水县| 阳城县| 天门市| 清流县|