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

Java?BOI與NIO超詳細(xì)實(shí)例精講

 更新時(shí)間:2022年11月11日 10:15:23   作者:頑石九變  
在Java的軟件設(shè)計(jì)開發(fā)中,通信架構(gòu)是不可避免的,我們?cè)谶M(jìn)行不同系統(tǒng)或者不同進(jìn)程之間的數(shù)據(jù)交互,或者在高并發(fā)下的通信場(chǎng)景下都需要用到網(wǎng)絡(luò)通信相關(guān)的技術(shù),對(duì)于一些經(jīng)驗(yàn)豐富的程序員來(lái)說(shuō),Java早期的網(wǎng)絡(luò)通信架構(gòu)存在一些缺陷,這篇文章介紹Java?BOI與NIO

Java BIO

阻塞IO,每個(gè)客戶端鏈接都需要一個(gè)獨(dú)立的線程處理,客戶端鏈接沒(méi)關(guān)閉時(shí),線程鏈接處于阻塞狀態(tài),直到客戶端鏈接關(guān)閉

如果客戶端鏈接沒(méi)有讀取到數(shù)據(jù),鏈接就會(huì)一直阻塞住,造成資源浪費(fèi)

示例代碼

開發(fā)一個(gè)ServerSocket服務(wù)端,通過(guò)telnet鏈接發(fā)送信息

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class BIOServerTest {
    public static void main(String[] args) throws Exception {
        ExecutorService pool = Executors.newCachedThreadPool();
        ServerSocket serverSocket = new ServerSocket(8888);
        System.out.println("服務(wù)端啟動(dòng)");
        while (true) {
            System.out.println("等待鏈接...");
            Socket socket = serverSocket.accept();
            pool.execute(() -> {
                handler(socket);
            });
        }
    }
    private static void handler(Socket socket) {
        try {
            System.out.println("有一個(gè)客戶端接入:" + Thread.currentThread().getName());
            byte[] bytes = new byte[1024];
            //通過(guò)socket 獲取輸入流
            InputStream inputStream = socket.getInputStream();
            //循環(huán)讀取客戶端發(fā)送的數(shù)據(jù)
            while (true) {
                System.out.println("等待讀取數(shù)據(jù)...");
                int read = inputStream.read(bytes);
                if (read != -1) {
                    //輸出客戶端讀取的數(shù)據(jù)
                    System.out.println("線程信息:" + Thread.currentThread().getName());
                    System.out.println(new String(bytes, 0, read));
                } else {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("關(guān)閉client鏈接:" + Thread.currentThread().getName());
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

通過(guò)telnet鏈接兩個(gè)客戶端,分別發(fā)送請(qǐng)求

從控制臺(tái)打印信息可以看出每一個(gè)鏈接對(duì)應(yīng)的線程都是獨(dú)立的

等待鏈接...
有一個(gè)客戶端接入:pool-1-thread-1
等待讀取數(shù)據(jù)...
線程信息:pool-1-thread-1
aaa
等待讀取數(shù)據(jù)...
線程信息:pool-1-thread-1
bbb
等待讀取數(shù)據(jù)...
等待鏈接...
有一個(gè)客戶端接入:pool-1-thread-2
等待讀取數(shù)據(jù)...
線程信息:pool-1-thread-2
ccc
等待讀取數(shù)據(jù)...
線程信息:pool-1-thread-2
ddd
等待讀取數(shù)據(jù)...

Java NIO

非阻塞IO,通過(guò)Selector和Channel,實(shí)現(xiàn)一個(gè)線程維護(hù)多個(gè)鏈接

NIO有三大核心部分:Channel(通道),Buffer(緩沖區(qū)),Selector(選擇器)

NOI是面向緩沖區(qū)編程的,數(shù)據(jù)讀取到一個(gè)它稍后處理的緩沖區(qū),需要時(shí)可在緩沖區(qū)中前后移動(dòng),增加的處理過(guò)程的靈活性,使用它可以提供非阻塞式的高伸縮性網(wǎng)絡(luò)

NIO是通過(guò)事件驅(qū)動(dòng)編程的,Selector會(huì)根據(jù)不同的事件,在各個(gè)通道上切換

Channel同時(shí)支持讀寫雙向處理

Selector能夠監(jiān)測(cè)到多個(gè)注冊(cè)的通到是否有事件發(fā)生,這樣就可以只用一個(gè)線程去管理多個(gè)通道,也就是管理多個(gè)鏈接和請(qǐng)求。

只有在鏈接真正有讀寫事件發(fā)生時(shí),才會(huì)進(jìn)行讀寫,大大減少了系統(tǒng)開銷,并且不必為每個(gè)鏈接創(chuàng)建一個(gè)線程

代碼解讀

  • 當(dāng)客戶端鏈接時(shí),會(huì)通過(guò)ServerSocketChannel得到SocketChannel
  • 將SocketChannel注冊(cè)到Selector上,一個(gè)selector上可以注冊(cè)多個(gè)SocketChannel
  • 通過(guò)socketChannel.register()方法注冊(cè)
  • 注冊(cè)后返回一個(gè)SelectionKey,會(huì)和該Selector關(guān)聯(lián)
  • Selector監(jiān)聽select方法,返回有事件發(fā)生的通道的個(gè)數(shù)
  • 進(jìn)一步得到有事件發(fā)生的各個(gè)SelectionKey,通過(guò)SelectionKey反向獲取SocketChannel
  • 通過(guò)得到的channel完成業(yè)務(wù)處理

1)服務(wù)端代碼

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class NIOServer {
    public static void main(String[] args) throws Exception {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        InetSocketAddress inetSocketAddress = new InetSocketAddress(7000);
        serverSocketChannel.socket().bind(inetSocketAddress);
        serverSocketChannel.configureBlocking(false);
        Selector selector = Selector.open();
        //注冊(cè)客戶端鏈接事件到selector
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        while (true) {
            int select = selector.select(1000L);
            if (select == 0) {
                System.out.println("等待1秒,沒(méi)有事件發(fā)生");
                continue;
            }
            //監(jiān)聽到相關(guān)事件發(fā)生,讀取SelectionKey集合,遍歷處理所有事件
            Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                if (key.isAcceptable()) {
                    SocketChannel socketChannel = serverSocketChannel.accept();
                    System.out.println("客戶端鏈接成功,生成一個(gè)sockeChannel " + socketChannel.hashCode());
                    //將socketChannel設(shè)置為非阻塞
                    socketChannel.configureBlocking(false);
                    //注冊(cè)內(nèi)容讀取事件到selector,同時(shí)關(guān)聯(lián)一個(gè)Buffer
                    socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                }
                if (key.isReadable()) {
                    SocketChannel channel = null;
                    try {
                        channel = (SocketChannel) key.channel();
                        ByteBuffer byteBuffer = (ByteBuffer) key.attachment();
                        int read = channel.read(byteBuffer);
                        System.out.println("讀取到數(shù)據(jù): " + new String(byteBuffer.array(), 0, read));
                    } catch (Exception e) {
                        if (channel != null) {
                            channel.close();
                        }
                        e.printStackTrace();
                    }
                }
                //手動(dòng)從集合中移除當(dāng)前的SelectionKey,防止重復(fù)操作
                keyIterator.remove();
            }
        }
    }
}

2)客戶端代碼

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
public class NIOClient {
    public static void main(String[] args) throws Exception {
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);
        InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 7000);
        if (!socketChannel.connect(inetSocketAddress)){
            while (!socketChannel.finishConnect()){
                System.out.println("鏈接未完成,客戶端不會(huì)阻塞....");
            }
        }
        String str = "Hello,你好~~~";
        ByteBuffer byteBuffer = ByteBuffer.wrap(str.getBytes());
        socketChannel.write(byteBuffer);
        System.in.read();
    }
}

控制臺(tái)輸出

等待1秒,沒(méi)有事件發(fā)生
等待1秒,沒(méi)有事件發(fā)生
等待1秒,沒(méi)有事件發(fā)生
等待1秒,沒(méi)有事件發(fā)生
等待1秒,沒(méi)有事件發(fā)生
客戶端鏈接成功,生成一個(gè)sockeChannel 60559178
讀取到數(shù)據(jù): Hello,你好~~~
等待1秒,沒(méi)有事件發(fā)生

到此這篇關(guān)于Java BOI與NIO超詳細(xì)實(shí)例精講的文章就介紹到這了,更多相關(guān)Java BOI與NIO內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • android中判斷服務(wù)或者進(jìn)程是否存在實(shí)例

    android中判斷服務(wù)或者進(jìn)程是否存在實(shí)例

    本篇文章主要介紹了android中判斷服務(wù)或者進(jìn)程是否存在實(shí)例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-05-05
  • 淺談Spring Cloud Ribbon的原理

    淺談Spring Cloud Ribbon的原理

    這篇文章主要介紹了淺談Spring Cloud Ribbon的原理,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • LongAdder原理及創(chuàng)建使用示例詳解

    LongAdder原理及創(chuàng)建使用示例詳解

    這篇文章主要為大家介紹了LongAdder原理及創(chuàng)建使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-01-01
  • Spring Cache使用RedisCache案例解析

    Spring Cache使用RedisCache案例解析

    這篇文章主要介紹了Spring Cache使用RedisCache案例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-10-10
  • 深入理解Spring事務(wù)及傳播機(jī)制之原理解析與實(shí)際應(yīng)用

    深入理解Spring事務(wù)及傳播機(jī)制之原理解析與實(shí)際應(yīng)用

    Spring事務(wù)管理機(jī)制提供了多種傳播行為,可以控制事務(wù)的范圍和隔離級(jí)別,保證數(shù)據(jù)一致性和完整性。在實(shí)際應(yīng)用中,需要根據(jù)具體業(yè)務(wù)場(chǎng)景選擇合適的傳播行為實(shí)現(xiàn)事務(wù)控制
    2023-04-04
  • 詳解Spring整合Quartz實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)

    詳解Spring整合Quartz實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù)

    本篇文章主要介紹了詳解Spring整合Quartz實(shí)現(xiàn)動(dòng)態(tài)定時(shí)任務(wù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-03-03
  • SpringBoot統(tǒng)一功能處理示例詳解(攔截器)

    SpringBoot統(tǒng)一功能處理示例詳解(攔截器)

    這篇文章主要介紹了SpringBoot統(tǒng)一功能處理(攔截器),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-08-08
  • 詳解SpringBoot時(shí)間參數(shù)處理完整解決方案

    詳解SpringBoot時(shí)間參數(shù)處理完整解決方案

    這篇文章主要介紹了詳解SpringBoot時(shí)間參數(shù)處理完整解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • Spring Security+JWT實(shí)現(xiàn)認(rèn)證與授權(quán)的實(shí)現(xiàn)

    Spring Security+JWT實(shí)現(xiàn)認(rèn)證與授權(quán)的實(shí)現(xiàn)

    本文主要介紹了Spring Security+JWT實(shí)現(xiàn)認(rèn)證與授權(quán)的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-04-04
  • Java中的cglib原理解析

    Java中的cglib原理解析

    這篇文章主要介紹了Java中的cglib原理解析,由于代理類繼承了被代理類,所以調(diào)用sayHello()方法時(shí)會(huì)直接調(diào)用代理類的sayHello()方法,而在代理類的方法中,調(diào)用了Callback的邏輯,需要的朋友可以參考下
    2023-10-10

最新評(píng)論

宿州市| 湖州市| 康定县| 杭锦后旗| 临潭县| 临泽县| 栾川县| 宜阳县| 尼玛县| 奈曼旗| 温泉县| 兴业县| 大丰市| 平顶山市| 永清县| 龙游县| 肇庆市| 城固县| 虞城县| 都江堰市| 略阳县| 乐都县| 白河县| 乌兰浩特市| 内江市| 江孜县| 乃东县| 龙里县| 昌宁县| 忻城县| 保靖县| 庆云县| 将乐县| 南京市| 朝阳区| 永宁县| 宣汉县| 大余县| 辽中县| 马边| 东方市|