国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

BIO、NIO線程模型

這篇具有很好參考價值的文章主要介紹了BIO、NIO線程模型。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

BIO(Blocking IO)

BIO(Blocking IO):同步阻塞模型,一個客戶端連接對應(yīng)一個處理線程,即:一個線程處理一個客戶端請求。
? ? 單線程版本: 服務(wù)端在處理完第一個客戶端的所有事件之前,無法為其他客戶端提供服務(wù)。
? ? 多線程版本:如果出現(xiàn)大量只連接不發(fā)數(shù)據(jù)的話,那么就會一直占用線程,浪費服務(wù)器資源。
? ? 線程池版本:用線程池根本不能根本的解決問題。假如我們有500個線程組成一個線程池,我們用這500個線程去為客戶端服務(wù)。那么,假設(shè)前500個客戶端請求進來,被占滿了這500個線程,并且這500個客戶端連接只連接不發(fā)數(shù)據(jù),那么我們的服務(wù)端不就崩掉了嗎?因為我們服務(wù)端最多只能處理500個客戶端連接,而你后面進來的,不管多少都會被我們的服務(wù)端拒之門外,所以用線程池也不能解決這個問題。

public class SocketServer {
    public static void main(String[] args) throws Exception {
        //創(chuàng)建了服務(wù)端,綁定到了9001端口
        ServerSocket serverSocket = new ServerSocket(9001);
        while (true) {
            System.out.println("等待連接..");
            //阻塞方法
            Socket clientSocket = serverSocket.accept(); //監(jiān)聽客戶端的連接,有客戶端的連接代碼才會往下走,沒有連接就會阻塞在這里
            System.out.println("有客戶端連接了..");

                        //1.單線程版本
            //handler(clientSocket);

            //2.多線程版本
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        handler(clientSocket);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();

            //3.線程池版本
            ExecutorService executorService = Executors.newFixedThreadPool(100);
            executorService.execute(new Runnable() {
                @Override
                public void run() {
                    try {
                        handler(clientSocket);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    //handler方法是處理客戶端事件的方法,比如客戶端發(fā)來數(shù)據(jù),在這里我們就做打印處理
    private static void handler(Socket clientSocket) throws Exception {
            byte[] bytes = new byte[1024];
            System.out.println("準備read..");
            //接收客戶端的數(shù)據(jù),阻塞方法,沒有數(shù)據(jù)可讀時就阻塞
            int read = clientSocket.getInputStream().read(bytes);
            System.out.println("read完畢。。");
            if (read != -1) {
                System.out.println("接收到客戶端的數(shù)據(jù):" + new String(bytes, 0, read));
            }
    }
}

NIO(Non Blocking IO)

NIO模型1.0版本(早期版本)

一個線程無限循環(huán)去list(存放著客戶端連接)輪訓(xùn),檢查是否有讀寫請求,如果有則處理,如果沒有跳過。這個版本如果連接數(shù)特別多的話,會有大量的無效遍歷,假如有1000個客戶端連接,只有其中100個有讀寫事件,那么還是會循環(huán)1000次,其中的900次循環(huán)都是無效的。

public class NioServer {

    // 保存客戶端連接
    static List<SocketChannel> channelList = new ArrayList<>();

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

        // 創(chuàng)建NIO ServerSocketChannel,與BIO的serverSocket類似,即創(chuàng)建了服務(wù)端并綁定了9001端口
        ServerSocketChannel serverSocket = ServerSocketChannel.open();
        serverSocket.socket().bind(new InetSocketAddress(9001));
        // 設(shè)置ServerSocketChannel為非阻塞
        serverSocket.configureBlocking(false);
        System.out.println("服務(wù)啟動成功");

        while (true) {
            // 非阻塞模式accept方法不會阻塞,否則會阻塞
            // NIO的非阻塞是由操作系統(tǒng)內(nèi)部實現(xiàn)的,底層調(diào)用了linux內(nèi)核的accept函數(shù)
            SocketChannel socketChannel = serverSocket.accept();
            if (socketChannel != null) { // 如果有客戶端進行連接
                System.out.println("連接成功");
                // 設(shè)置SocketChannel為非阻塞
                socketChannel.configureBlocking(false);
                // 保存客戶端連接在List中
                channelList.add(socketChannel);
            }
            // 遍歷連接進行數(shù)據(jù)讀取  讀寫事件
            Iterator<SocketChannel> iterator = channelList.iterator();
            while (iterator.hasNext()) {
                SocketChannel sc = iterator.next();
                ByteBuffer byteBuffer = ByteBuffer.allocate(128);
                // 非阻塞模式read方法不會阻塞,否則會阻塞
                int len = sc.read(byteBuffer);
                // 如果有數(shù)據(jù),把數(shù)據(jù)打印出來,整個過程是一個main線程在處理
                if (len > 0) {
                    System.out.println(Thread.currentThread().getName() + " 接收到消息:" + new String(byteBuffer.array()));
                } else if (len == -1) { // 如果客戶端斷開,把socket從集合中去掉
                    iterator.remove();
                    System.out.println("客戶端斷開連接");
                }
            }
        }
    }
}

NIO模型2.0版本(啟用多路復(fù)用器,jdk1.4以上)

客戶端發(fā)送的連接請求都會注冊到多路復(fù)用器selector上,多路復(fù)用器輪詢到連接有IO請求就進行處理,JDK1.4開始引入。這個版本進行了很大程度的優(yōu)化,當客戶端連接以后,如果有讀寫事件,則會加入一個隊列里,處理事件的線程會阻塞等待這個隊列里有新的元素之后處理事件。

步驟:

  1. 創(chuàng)建ServerSocketChannel服務(wù)端
  2. 創(chuàng)建多路復(fù)用器Selector( 每個操作系統(tǒng)創(chuàng)建出來的是不一樣的,Centos創(chuàng)建的是EPollSelectorProviderImpl,Windows創(chuàng)建的是WindowsSelectorImpl,其實就是Linux的Epoll實例EPollArrayWrapper)
  3. ServerSocketChannel將建立連接事件注冊到Selector中(register方法往EPollArrayWrapper中添加元素)
  4. 處理事件
    1. 如果是建立連接事件,則把客戶端的讀寫請求也注冊到Selector中
    2. 如果是讀寫事件則按業(yè)務(wù)處理
public class NioSelectorServer {

    public static void main(String[] args) throws IOException {
        //指定感興趣的操作類型為 OP_ACCEPT
        int OP_ACCEPT = 1 << 4;
        System.out.println(OP_ACCEPT);

        // 創(chuàng)建NIO ServerSocketChannel
        ServerSocketChannel serverSocket = ServerSocketChannel.open();
        serverSocket.socket().bind(new InetSocketAddress(9001));
        // 設(shè)置ServerSocketChannel為非阻塞
        serverSocket.configureBlocking(false);
        // 打開Selector處理Channel,即創(chuàng)建epoll,這里啟用了多路復(fù)用器是與NIO1.0版本最大的區(qū)別
        Selector selector = Selector.open();
        // 把ServerSocketChannel注冊到selector上,并且selector對客戶端accept連接操作感興趣(把連接事件注冊到多路復(fù)用器里面)
        SelectionKey selectionKey = serverSocket.register(selector, SelectionKey.OP_ACCEPT);//通過 SelectionKey.OP_ACCEPT 來識別和處理接受連接事件。
        System.out.println("服務(wù)啟動成功");

        while (true) {
            // 阻塞等待需要處理的事件發(fā)生 已注冊事件發(fā)生后,會執(zhí)行后面邏輯
            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ù)可以注冊寫事件
                    SelectionKey selKey = 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(Thread.currentThread().getName() +  "接收到消息:" + new String(byteBuffer.array()));
                    } else if (len == -1) { // 如果客戶端斷開連接,關(guān)閉Socket
                        System.out.println("客戶端斷開連接");
                        socketChannel.close();
                    }
                }
                //從事件集合里刪除本次處理的key,防止下次select重復(fù)處理
                iterator.remove();
            }
        }
    }
}

Redis線程模型

Redis就是典型的基于epoll的NIO線程模型(nginx也是),epoll實例收集所有事件(連接與讀寫事件),由一個服務(wù)端線程連續(xù)處理所有事件命令。文章來源地址http://www.zghlxwxcb.cn/news/detail-492721.html

到了這里,關(guān)于BIO、NIO線程模型的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔相關(guān)法律責任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【Linux學(xué)習】多線程——同步 | 條件變量 | 基于阻塞隊列的生產(chǎn)者消費者模型

    【Linux學(xué)習】多線程——同步 | 條件變量 | 基于阻塞隊列的生產(chǎn)者消費者模型

    ??作者:一只大喵咪1201 ??專欄:《Linux學(xué)習》 ??格言: 你只管努力,剩下的交給時間! 以生活中消費者生產(chǎn)者為例: 生活中,我們大部分人都扮演著消費者的角色,會經(jīng)常在超市買東西,比如買方便面,而超市的方便面是由供應(yīng)商生成的。所以我們就是消費者,供應(yīng)商

    2024年02月05日
    瀏覽(16)
  • BIO、NIO、IO多路復(fù)用模型詳細介紹&Java NIO 網(wǎng)絡(luò)編程

    BIO、NIO、IO多路復(fù)用模型詳細介紹&Java NIO 網(wǎng)絡(luò)編程

    上文介紹了網(wǎng)絡(luò)編程的基礎(chǔ)知識,并基于 Java 編寫了 BIO 的網(wǎng)絡(luò)編程。我們知道 BIO 模型是存在巨大問題的,比如 C10K 問題,其本質(zhì)就是因其阻塞原因,導(dǎo)致如果想要承受更多的請求就必須有足夠多的線程,但是足夠多的線程會帶來內(nèi)存占用問題、CPU上下文切換帶來的性能問題

    2024年02月14日
    瀏覽(30)
  • Java中的三種I/O模型:BIO、NIO和AIO

    I/O(輸入/輸出)操作是任何應(yīng)用程序中必不可少的一部分,它涉及到與文件、網(wǎng)絡(luò)或其他設(shè)備之間的數(shù)據(jù)傳輸。Java提供了幾種不同的I/O模型,其中最常見的是AIO(異步非阻塞I/O)、BIO(阻塞I/O)和NIO(非阻塞I/O)。這些模型在處理I/O操作時具有不同的工作方式、特性和適用

    2024年02月08日
    瀏覽(22)
  • 【Netty專題】【網(wǎng)絡(luò)編程】從OSI、TCP/IP網(wǎng)絡(luò)模型開始到BIO、NIO(Netty前置知識)

    【Netty專題】【網(wǎng)絡(luò)編程】從OSI、TCP/IP網(wǎng)絡(luò)模型開始到BIO、NIO(Netty前置知識)

    我是有點怕網(wǎng)絡(luò)編程的,總有點【談網(wǎng)色變】的感覺。為了讓自己不再【談網(wǎng)色變】,所以我想過系統(tǒng)學(xué)習一下,然后再做個筆記這樣,加深一下理解。但是真要系統(tǒng)學(xué)習,其實還是要花費不少時間的,所以這里也只是簡單的,盡可能地覆蓋一下,梳理一些我認為比較迫切需

    2024年02月06日
    瀏覽(28)
  • NIO與BIO

    當談到 Java 網(wǎng)絡(luò)編程時,經(jīng)常會聽到兩個重要的概念:BIO(Blocking I/O,阻塞 I/O)和 NIO(Non-blocking I/O,非阻塞 I/O)。它們都是 Java 中用于處理 I/O 操作的不同編程模型。 BIO 是 Java 最早的 I/O 模型,也是最簡單的一種。在 BIO 模型中,每個 I/O 操作都會阻塞當前線程,直到數(shù)據(jù)

    2024年04月10日
    瀏覽(19)
  • 33. bio和nio

    33. bio和nio

    1.1 bio網(wǎng)絡(luò)模型示意圖 單個客戶端向服務(wù)器發(fā)起請求時,請求順序如下: 多個客戶端向一個服務(wù)器發(fā)起請求時,請求順序如下: 1.2 bio網(wǎng)絡(luò)模型缺點 1.阻塞式I/O 2.彈性伸縮能力差 3.多線程耗費資源 2.1 nio網(wǎng)絡(luò)模型示意圖 單個客戶端向服務(wù)器發(fā)起請求時,請求順序如下: 2.2 ni

    2024年02月17日
    瀏覽(20)
  • BIO、NIO和AIO

    BIO、NIO和AIO

    目錄 一.引言 何為IO IO的過程 Java的3種網(wǎng)絡(luò)IO模型 阻塞和非阻塞IO IO多路復(fù)用 異步和同步IO 二.BIO 三.NIO 1. 三大組件 Channel Buffer Selector 2.ByteBuffer 2.1ByteBuffer的使用 2.2ByteBuffer 結(jié)構(gòu) ?2.3ByteBuffer的常用方法 分配空間 ? 向 buffer 寫入數(shù)據(jù) 從 buffer 讀取數(shù)據(jù) 字符串與 ByteBuffer 互轉(zhuǎn) 分

    2024年02月12日
    瀏覽(23)
  • BIO、NIO、AIO 的區(qū)別

    Java面試題? 阻塞IO。一個連接一個線程,當服務(wù)端接受到多個客戶端的請求時,客戶端有連接請求時服務(wù)器端就需要啟動一個線程進行處理,如果這個連接不做任何事情會造成不必要的線程開銷 同步非阻塞IO 。一個線程處理多個連接。NIO 包含? Channel(通道)、Selector(選擇

    2024年01月20日
    瀏覽(20)
  • 【java】BIO、NIO、AIO

    同步阻塞IO,使用BIO讀取數(shù)據(jù)時,線程會阻塞住,并且需要線程主動去查詢是否有數(shù)據(jù)可讀,并且需要處理完一個Socket之后才能處理下一個Socket 在這種模型下,每個 I/O 操作都會阻塞當前線程,直到操作完成才會返回。這意味著當一個線程執(zhí)行 I/O 操作時,它會被阻塞,無法執(zhí)

    2024年04月10日
    瀏覽(23)
  • BIO、NIO、AIO區(qū)別詳解

    主線程發(fā)起io請求后,需要等待當前io操作完成,才能繼續(xù)執(zhí)行。 引入selector、channel、等概念,當主線程發(fā)起io請求后,輪詢的查看系統(tǒng)是否準備好執(zhí)行io操作,沒有準備好則主線程不會阻塞會繼續(xù)執(zhí)行,準備好主線程會阻塞等待io操作完成。 主線程發(fā)起io請求后,不會阻塞,

    2024年02月07日
    瀏覽(29)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包