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

Java?NIO通信基礎示例詳解

 更新時間:2023年10月27日 10:19:22   作者:田埂  
這篇文章主要為大家介紹了Java?NIO通信基礎使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

Java NIO 通信基礎介紹

高性能的 Java 通信,絕對離不開 Java NIO 技術,現(xiàn)在主流的技術框架或中間件服務器,都使 用了 Java NIO 技術,譬如:Tomcat、Jetty、Netty。

Java NIO 由以下三個核心組件組成:

  • Channel(通道)
  • Buffer(緩沖區(qū))
  • Selector(選擇器)

NIO 和 OIO 的對比

在 Java 中,NIO 和 OIO 的區(qū)別,主要體現(xiàn)在三個方面:

  • OIO 是面向流(Stream Oriented)的,NIO 是面向緩沖區(qū)(Buffer Oriented)的。 何謂面向流,何謂面向緩沖區(qū)呢? OIO 是面向字節(jié)流或字符流的,在一般的 OIO 操作中,我們以流式的方式順序地從一個流中讀取一個或多個字節(jié),因此,我們不能隨意地改變讀取指針的位置。而在 NIO 操作中則不同,NIO 中引入了 Channel(通道)和 Buffer(緩沖區(qū))的概念。讀取和寫入,只需要從通道中讀取數(shù)據(jù)到緩沖區(qū)中,或?qū)?shù)據(jù)從緩沖區(qū)中寫入到通道中。NIO 不像 OIO 那樣是順序操作,可以隨意地讀取 Buffer 中任意位置的數(shù)據(jù)。
  • OIO 的操作是阻塞的,而 NIO 的操作是非阻塞的。 NIO 如何做到非阻塞的呢?大家都知道,OIO 操作都是阻塞的,例如,我們調(diào)用一個 read 方法讀取一個文件的內(nèi)容,那么調(diào)用 read 的線程會被阻塞住,直到 read 操作完成。 而在 NIO 的非阻塞模式中,當我們調(diào)用 read 方法時,如果此時有數(shù)據(jù),則 read 讀取數(shù)據(jù)并返回;如果此時沒有數(shù)據(jù),則 read 直接返回,而不會阻塞當前線程。NIO 的非阻塞,是如何做到的呢?NIO 使用了通道和通道的多路復用技術。
  • OIO 沒有選擇器(Selector)概念,而 NIO 有選擇器的概念。 NIO 的實現(xiàn),是基于底層的選擇器的系統(tǒng)調(diào)用。NIO 的選擇器,需要底層操作系統(tǒng)提供支持。 而 OIO 不需要用到選擇器。

使用 FileChannel 完成文件復制的實踐案例

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
public class MyCopyFile {
    private File inFile;
    private File outFile;
    private FileInputStream fis = null;
    private FileOutputStream fos = null;
    private FileChannel fisChannel = null;
    private FileChannel fosChannel = null;
    //復制文件
    public void copyFile(String srcPath, String destPath) throws IOException {
        try {
            inFile = new File(srcPath);
            outFile = new File(destPath);
            fis = new FileInputStream(inFile);
            fos = new FileOutputStream(outFile);
            fisChannel = fis.getChannel();
            fosChannel = fos.getChannel();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            int length = -1;
            while ((length = fisChannel.read(buffer)) != -1) {
                buffer.flip();
                int outLenth = 0;
                while ((outLenth = fosChannel.write(buffer)) != 0) {
                    System.out.println("讀取的字節(jié)數(shù)為:" + outLenth);
                }
                buffer.clear();
            }
            //強制刷新磁盤
            fosChannel.force(true);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            fosChannel.close();
            fos.close();
            fisChannel.close();
            fis.close();
        }
    }
    public static void main(String[] args) throws IOException {
        MyCopyFiletest = new MyCopyFile();
        String s1 = "D:\\maze.txt";
        String s2 = "D:\\maze1.txt";
        MyCopyFile.copyFile(s1, s2);
    }
}

使用 DatagramChannel 數(shù)據(jù)包通道發(fā)送數(shù)據(jù)的實踐案例

功能:

獲取用戶的輸入數(shù)據(jù),通過 DatagramChannel 數(shù)據(jù)報通道,將數(shù)據(jù)發(fā)送到遠程的服務器。

客戶端代碼:

public class Client {
    //Client發(fā)送信息
    public void send() throws IOException {
        DatagramChannel dChannel = DatagramChannel.open();
        dChannel.configureBlocking(false);
        ByteBuffer buf = ByteBuffer.allocate(1024);
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            String s = sc.nextLine();
            buf.put(s.getBytes());
            buf.flip();
            dChannel.send(buf, new InetSocketAddress("127.0.0.1", 9999));
            buf.clear();
        }
        dChannel.close();
    }
    public static void main(String[] args) throws IOException {
        new Client().send();
    }
}

服務端代碼:

public class Server {
    //服務端接收 用戶發(fā)來的信息
    public void receive() throws IOException {
        DatagramChannel serverChannel = DatagramChannel.open();
        //設置成非阻塞模式
        serverChannel.configureBlocking(false);
        serverChannel.bind(new InetSocketAddress("127.0.0.1", 9999));
        Selector selector = Selector.open();
        serverChannel.register(selector, SelectionKey.OP_READ);
        while (selector.select() > 0) {
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            while (iterator.hasNext()) {
                SelectionKey next = iterator.next();
                if (next.isReadable()) {
                    SocketAddress receive = serverChannel.receive(buffer);
                    buffer.flip();
                    String s = new String(buffer.array(), 0, buffer.limit());
                    System.out.println(s);
                    buffer.clear();
                }
            }
            iterator.remove();
        }
        //關閉選擇器和通道
        selector.close();
        serverChannel.close();
    }
    public static void main(String[] args) throws IOException {
        new Server().receive();
    }
}

使用 NIO 實現(xiàn) Discard 服務器的實踐案例

功能:

僅僅讀取客戶端通道的輸入數(shù)據(jù),讀取完成后直接關閉客戶端通道;并且讀取到的數(shù)據(jù)直接拋棄掉

Discard 服務器代碼:

public class SocketServerDemo {
    public void receive() throws IOException {
        //創(chuàng)建服務器的通道
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        //設置為非阻塞模式
        serverSocketChannel.configureBlocking(false);
        //開啟選擇器
        Selector selector = Selector.open();
        //綁定鏈接
        serverSocketChannel.bind(new InetSocketAddress(9999));
        //將通道的某個IO事件  注冊到選擇器上
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        //輪詢所有就緒的IO事件
        while (selector.select() > 0) {
            //逐個獲取IO事件
            Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
            //逐個判斷該IO事件是否為想要的
            while (iterator.hasNext()) {
                SelectionKey next = iterator.next();
                if (next.isAcceptable()) {
                    //如果為該事件為“連接就緒”事件,就獲取客戶端的鏈接
                    SocketChannel clientSocket = serverSocketChannel.accept();
                    //將客戶端的鏈接設置為非阻塞模式
                    clientSocket.configureBlocking(false);
                    //將新的通道的可讀事件,注冊到選擇器上
                    clientSocket.register(selector, SelectionKey.OP_READ);
                } else if (next.isReadable()) {
                    //若IO事件為“可讀事件”,讀取數(shù)據(jù)
                    SocketChannel clientSocket = (SocketChannel) next.channel();
                    //創(chuàng)建緩沖區(qū)
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int length = 0;
                    //讀取事件 讓后丟棄
                    while ((length = clientSocket.read(buffer)) > 0) {
                        buffer.flip();
                        String s = new String(buffer.array(), 0, length);
                        System.out.println(s);
                        buffer.clear();
                    }
                    clientSocket.close();
                }
                //移除選擇鍵
                iterator.remove();
            }
        }
        serverSocketChannel.close();
    }
    public static void main(String[] args) throws IOException {
        new SocketServerDemo().receive();
    }
}

客戶端的 DiscardClient 代碼:

public class SocketClientDemo {
    public void socketClient() throws IOException {
        SocketChannel clientSocket = SocketChannel.open(new InetSocketAddress(9999));
        //切換成非阻塞模式
        clientSocket.configureBlocking(false);
        //如果沒有連接完成 就一直鏈接
        while (!clientSocket.finishConnect()){
        }
        //執(zhí)行到這里說明已經(jīng)連接完成了
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        buffer.put("Hello SocketService".getBytes());
        buffer.flip();
        clientSocket.write(buffer);
        clientSocket.shutdownInput();
        clientSocket.close();
    }
    public static void main(String[] args) throws IOException {
        new SocketClientDemo().socketClient();
    }
}

與 Java OIO 相比,Java NIO 編程大致的特點如下:

(1)在 NIO 中,服務器接收新連接的工作,是異步進行的。不像 Java 的 OIO 那樣,服務器監(jiān)聽連接,是同步的、阻塞的。NIO 可以通過選擇器(也可以說成:多路復用器),后續(xù)不斷地輪詢選擇器的選擇鍵集合,選擇新到來的連接。

(2)在 NIO 中,SocketChannel 傳輸通道的讀寫操作都是異步的。如果沒有可讀寫的數(shù)據(jù),負責 IO 通信的線程不會同步等待。這樣,線程就可以處理其他連接的通道;不需要像 OIO 那樣,線程一直阻塞,等待所負責的連接可用為止。

(3)在 NIO 中,一個選擇器線程可以同時處理成千上萬個客戶端連接,性能不會隨著客戶端的增加而線性下降。

以上就是Java NIO通信基礎示例詳解的詳細內(nèi)容,更多關于Java NIO通信基礎的資料請關注腳本之家其它相關文章!

相關文章

  • IDEA如何將Java項目打包成可執(zhí)行的Jar包

    IDEA如何將Java項目打包成可執(zhí)行的Jar包

    在Java開發(fā)中,我們通常會將我們的項目打包成可執(zhí)行的Jar包,以便于在其他環(huán)境中部署和運行,本文將介紹如何使用IDEA集成開發(fā)環(huán)境將Java項目打包成可執(zhí)行的Jar包,感興趣的朋友一起看看吧
    2023-07-07
  • Java基礎之文件和目錄操作

    Java基礎之文件和目錄操作

    這篇文章主要介紹了Java基礎之文件和目錄操作,文中有非常詳細的代碼示例,對正在學習java基礎的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • Java實現(xiàn)遞歸計算n的階乘

    Java實現(xiàn)遞歸計算n的階乘

    這篇文章主要為大家詳細介紹了Java實現(xiàn)遞歸計算n的階乘,利用遞歸的思想實現(xiàn)階乘的計算,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Java基礎之引用相關知識總結

    Java基礎之引用相關知識總結

    今天聊聊Java的引用,大多數(shù)時候我們說引用都是強引用,只有在對象不使用的情況下才會釋放內(nèi)存,其實Java 內(nèi)存有四種不同的引用.一起看看吧,,需要的朋友可以參考下
    2021-05-05
  • JAVA序列化和反序列化的底層實現(xiàn)原理解析

    JAVA序列化和反序列化的底層實現(xiàn)原理解析

    這篇文章主要介紹了JAVA序列化和反序列化的底層實現(xiàn)原理解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • Java基于鏈表實現(xiàn)棧的方法詳解

    Java基于鏈表實現(xiàn)棧的方法詳解

    這篇文章主要介紹了Java基于鏈表實現(xiàn)棧的方法,結合實例形式詳細分析了Java基于鏈表實現(xiàn)棧的原理、操作步驟與相關注意事項,需要的朋友可以參考下
    2020-03-03
  • SpringBoot整合jersey的示例代碼

    SpringBoot整合jersey的示例代碼

    本篇文章主要介紹了SpringBoot整合jersey的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 在?Spring?Boot?中使用?Quartz?調(diào)度作業(yè)的示例詳解

    在?Spring?Boot?中使用?Quartz?調(diào)度作業(yè)的示例詳解

    這篇文章主要介紹了在?Spring?Boot?中使用?Quartz?調(diào)度作業(yè)的示例詳解,在本文中,我們將看看如何使用Quartz框架來調(diào)度任務,Quartz支持在特定時間運行作業(yè)、重復作業(yè)執(zhí)行、將作業(yè)存儲在數(shù)據(jù)庫中以及Spring集成,需要的朋友可以參考下
    2022-07-07
  • Java實現(xiàn)簡單雙色球搖獎功能過程解析

    Java實現(xiàn)簡單雙色球搖獎功能過程解析

    這篇文章主要介紹了Java實現(xiàn)簡單雙色球搖獎功能過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-09-09
  • Spring?AOP中三種增強方式的示例詳解

    Spring?AOP中三種增強方式的示例詳解

    AOP?(Aspect?Orient?Programming),直譯過來就是?面向切面編程。AOP?是一種編程思想,是面向?qū)ο缶幊蹋∣OP)的一種補充。本文為大家介紹了Spring?AOP中三種增強方式,感興趣的可以了解一下
    2022-07-07

最新評論

化州市| 新丰县| 台中市| 团风县| 新津县| 香港| 阜南县| 集安市| 昌乐县| 青川县| 贵州省| 洛川县| 大宁县| 夏河县| 黄冈市| 十堰市| 偃师市| 陆良县| 汶川县| 峨边| 青阳县| 如皋市| 右玉县| 邵阳县| 得荣县| 武城县| 宜阳县| 广宗县| 崇明县| 宁海县| 鄂尔多斯市| 三台县| 宁南县| 南京市| 马尔康县| 九江市| 赣榆县| 昌江| 长子县| 白银市| 中牟县|