欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java圖文并茂詳解NIO與零拷貝

 更新時(shí)間:2022年11月11日 09:49:07   作者:頑石九變  
零拷貝是網(wǎng)絡(luò)編程的關(guān)鍵,很多性能優(yōu)化都離不開。在?Java?程序中,常用的零拷貝有?mmap(memory?map,內(nèi)存映射)?和?sendFile。那么它們在?OS(操作系統(tǒng))?中,到底是怎么樣的一個(gè)的設(shè)計(jì)?另外我們看下NIO?中如何使用零拷貝

零拷貝指的是沒有CPU拷貝,并不是不拷貝;減少上下文切換

一、概念說明

1、傳統(tǒng)IO

需要4次拷貝,3次上下文切換

2、mmap

mmap 通過內(nèi)存映射,將文件映射到內(nèi)存緩沖區(qū),同時(shí)用戶空間可以共享內(nèi)存緩沖區(qū)的數(shù)據(jù),減少內(nèi)核空間到用戶空間的拷貝

需要3次拷貝,3次上下文切換

3、sendfile

Linux 2.4 避免了從內(nèi)核緩沖區(qū)到Socket Buffer的拷貝,直接拷貝到協(xié)議棧,從而減少一次數(shù)據(jù)拷貝

需要2次拷貝,3次上下文切換

4、mmap與sendfile

mmap適合小數(shù)據(jù)量讀寫,sendfile適合大文件傳輸

mmap需要4次上下文切換,3次數(shù)據(jù)拷貝;sendfile需要3次上下文切換,最少2次數(shù)據(jù)拷貝

send可用利用DMA方式,減少CPU拷貝,mmap則不能(必須從內(nèi)核拷貝到Socket緩沖區(qū))

二、傳統(tǒng)IO傳輸文件代碼示例

1、服務(wù)端代碼

import java.io.DataInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class BIOServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(7000);
        while (true) {
            Socket socket = serverSocket.accept();
            DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());
            try {
                long total = 0;
                byte[] bytes = new byte[4096];
                FileOutputStream fileOutputStream = new FileOutputStream("d:\\temp\\04.zip");
                while (true) {
                    int read = dataInputStream.read(bytes, 0, bytes.length);
                    if (read == -1) {
                        //文件讀取結(jié)束,退出循環(huán)
                        break;
                    }
                    total += read;
                    fileOutputStream.write(bytes, 0, read);
                }
                System.out.println("收到客戶端發(fā)送文件,總字節(jié)數(shù):" + total);
                fileOutputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

2、客戶端代碼

import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.Socket;
public class BIOClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("127.0.0.1", 7000);
        FileInputStream fileInputStream = new FileInputStream("d:\\temp\\03.zip");
        DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
        byte[] bytes = new byte[4096];
        long readCount;
        long total = 0;
        long start = System.currentTimeMillis();
        while ((readCount = fileInputStream.read(bytes)) >= 0) {
            total += readCount;
            dataOutputStream.write(bytes);
        }
        System.out.println("發(fā)送總字節(jié)數(shù):" + total + ", 總耗時(shí):" + (System.currentTimeMillis() - start));
        dataOutputStream.close();
        socket.close();
        fileInputStream.close();
    }
}

3、控制臺出輸出

測試發(fā)送9M的壓縮文件,耗時(shí)在26ms左右

發(fā)送總字節(jié)數(shù):9428963, 總耗時(shí):26

三、NIO傳輸文件代碼示例

1、服務(wù)端代碼

package com.hj.io.nio.zero;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
public class NIOServerFile {
    public static void main(String[] args) throws IOException {
        InetSocketAddress address = new InetSocketAddress(7000);
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(address);
        //創(chuàng)建buffer
        ByteBuffer byteBuffer = ByteBuffer.allocate(4096);
        while (true) {
            //等待客戶端鏈接
            SocketChannel socketChannel = serverSocketChannel.accept();
            System.out.println("收到客戶端鏈接");
            int total = 0;
            FileOutputStream fileOutputStream = new FileOutputStream("d:\\temp\\05.zip");
            //循環(huán)讀取數(shù)據(jù),并存儲到硬盤
            while (true) {
                try {
                    int readCount = socketChannel.read(byteBuffer);
                    if (readCount == -1) {
                        //文件讀取結(jié)束
                        break;
                    }
                    total += readCount;
                    fileOutputStream.write(byteBuffer.array(),0,readCount);
                    //將buffer倒帶
                    byteBuffer.rewind();
                } catch (IOException e) {
                   break;
                }
            }
            System.out.println("收到客戶端發(fā)送文件,總字節(jié)數(shù):" + total);
            fileOutputStream.close();
        }
    }
}

2、客戶端代碼

import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
public class NIOClientFile {
    public static void main(String[] args) throws IOException {
        //打開一個(gè)SocketChannel并鏈接到服務(wù)器端
        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 7000));
        //打開一個(gè)文件
        FileChannel fileChannel = new FileInputStream("d:\\temp\\03.zip").getChannel();
        //發(fā)送文件到服務(wù)器
        long start = System.currentTimeMillis();
        //在linux下,一次transferTo調(diào)用就可以完成傳輸
        //在windows下,一次transferTo調(diào)用最多只能傳8M,大文件需要分段傳輸,需要注意傳輸位置
        //transferTo底層使用零拷貝
        long total = fileChannel.size();
        long sended = 0;
        while (sended < total) {
            //從上一次傳輸位置繼續(xù)發(fā)送
            long lenth = fileChannel.transferTo(sended, fileChannel.size(), socketChannel);
            sended += lenth;
        }
        System.out.println("發(fā)送總字節(jié)數(shù):" + sended + ",總耗時(shí):" + (System.currentTimeMillis() - start));
        //關(guān)閉channel
        fileChannel.close();
        socketChannel.close();
    }
}

3、控制臺出輸出

測試發(fā)送9M的壓縮文件,耗時(shí)在16ms左右

發(fā)送總字節(jié)數(shù):9428963,總耗時(shí):16

四、總結(jié)

使用零拷貝傳輸,性能明顯高于傳統(tǒng)IO傳輸

到此這篇關(guān)于Java圖文并茂詳解NIO與零拷貝的文章就介紹到這了,更多相關(guān)Java NIO與零拷貝內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 深入理解Java設(shè)計(jì)模式之訪問者模式

    深入理解Java設(shè)計(jì)模式之訪問者模式

    這篇文章主要介紹了JAVA設(shè)計(jì)模式之訪問者模式的的相關(guān)資料,文中示例代碼非常詳細(xì),供大家參考和學(xué)習(xí),感興趣的朋友可以了解
    2021-11-11
  • SpringCloud Feign遠(yuǎn)程調(diào)用實(shí)現(xiàn)詳解

    SpringCloud Feign遠(yuǎn)程調(diào)用實(shí)現(xiàn)詳解

    Feign是Netflix公司開發(fā)的一個(gè)聲明式的REST調(diào)用客戶端; Ribbon負(fù)載均衡、 Hystrⅸ服務(wù)熔斷是我們Spring Cloud中進(jìn)行微服務(wù)開發(fā)非常基礎(chǔ)的組件,在使用的過程中我們也發(fā)現(xiàn)它們一般都是同時(shí)出現(xiàn)的,而且配置也都非常相似
    2022-11-11
  • Java在重載中使用Object的問題

    Java在重載中使用Object的問題

    這篇文章主要介紹了Java在重載中使用Object的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Hibernate Validation自定義注解校驗(yàn)的實(shí)現(xiàn)

    Hibernate Validation自定義注解校驗(yàn)的實(shí)現(xiàn)

    這篇文章主要介紹了Hibernate Validation自定義注解校驗(yàn)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04
  • 深入理解hibernate的三種狀態(tài)

    深入理解hibernate的三種狀態(tài)

    本篇文章主要介紹了深入理解hibernate的三種狀態(tài) ,主要包括了transient(瞬時(shí)狀態(tài)),persistent(持久化狀態(tài))以及detached(離線狀態(tài)),有興趣的同學(xué)可以了解一下
    2017-05-05
  • Java時(shí)間輪算法的實(shí)現(xiàn)代碼示例

    Java時(shí)間輪算法的實(shí)現(xiàn)代碼示例

    本篇文章主要介紹了Java時(shí)間輪算法的實(shí)現(xiàn)代碼示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-08-08
  • idea中怎樣創(chuàng)建并運(yùn)行第一個(gè)java程序

    idea中怎樣創(chuàng)建并運(yùn)行第一個(gè)java程序

    這篇文章主要介紹了idea中怎樣創(chuàng)建并運(yùn)行第一個(gè)java程序問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • Springboot項(xiàng)目保存本地系統(tǒng)日志文件的實(shí)現(xiàn)方法

    Springboot項(xiàng)目保存本地系統(tǒng)日志文件的實(shí)現(xiàn)方法

    這篇文章主要介紹了Springboot項(xiàng)目保存本地系統(tǒng)日志文件的實(shí)現(xiàn)方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2021-04-04
  • Java?斷言?assert的用法詳解

    Java?斷言?assert的用法詳解

    Java?assert斷言機(jī)制是Java5中推出的新特性,它主要用于在程序運(yùn)行時(shí)檢查狀態(tài)或假設(shè)的正確性,本篇文章將全面詳細(xì)地講解Java?assert斷言機(jī)制,包括斷言概述、語法規(guī)則、工作原理、使用場景、注意事項(xiàng)以及示例代碼等方面,需要的朋友可以參考下
    2023-05-05
  • 解決使用IDEA時(shí)跳轉(zhuǎn)到.class的問題

    解決使用IDEA時(shí)跳轉(zhuǎn)到.class的問題

    這篇文章主要介紹了解決使用IDEA時(shí)跳轉(zhuǎn)到.class的問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08

最新評論