AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

Java Nio FileChannel堆內堆外數據讀寫全流程分析及使用

來源: 責編: 時間:2024-05-27 08:57:11 135觀看
導讀背景java nio中文件讀寫不管是普通文件讀寫,還是基于mmap實現零拷貝,都離不開FileChannel這個類。隨便打開RocketMQ 源碼搜索FileChannel。就可以看到使用頻率。圖片kafka也是。圖片所以在java中文件讀寫FileChannel尤

背景

java nio中文件讀寫不管是普通文件讀寫,還是基于mmap實現零拷貝,都離不開FileChannel這個類。VG728資訊網——每日最新資訊28at.com

隨便打開RocketMQ 源碼搜索FileChannel。VG728資訊網——每日最新資訊28at.com

就可以看到使用頻率。VG728資訊網——每日最新資訊28at.com

圖片圖片VG728資訊網——每日最新資訊28at.com

kafka也是。VG728資訊網——每日最新資訊28at.com

圖片圖片VG728資訊網——每日最新資訊28at.com

所以在java中文件讀寫FileChannel尤為重用。VG728資訊網——每日最新資訊28at.com

java文件讀寫全流程

圖片圖片VG728資訊網——每日最新資訊28at.com

這里說的僅僅是FileChannel基于堆內存(HeapByteBuffer)的文件讀寫。VG728資訊網——每日最新資訊28at.com

如果是mmap或者堆外內存,可能有些步驟會省略,相當于有一些優化。VG728資訊網——每日最新資訊28at.com

  1. FileChannel調用read,將HeapByteBuffer拷貝到DirectByteBuffer。
  2. JVM在native層使用read系統調用進行文件讀取, 這里需要進行上下文切換,從用戶態進入內核態。
  3. JVM 進程進入虛擬文件系統層,查看文件數據再page cache是否緩存,如果有則直接從page cache讀取并返回到DirectByteBuffer。
  4. 如果請求文件數據不在page caceh,則進入文件系統。通過塊驅動設備進行真正的IO,并進行文件預讀,比如讀取的文件可能只有1-10,但是會將1-20都讀取。
  5. 磁盤控制器DMA將磁盤中的數據拷貝到page cache中。這里發生了一次數據拷貝(非CPU拷貝)。
  6. CPU將page cache數據拷貝到DirectByteBuffer,因為page cache屬于內核空間,JVM進程無法直接尋址。這里是發生第二次數據拷貝。
  7. JVM進程從內核態切換回用戶態,這里如果使用的是堆內存(HeapByteBuffer),實際還需要將堆外內存DirectByteBuffer拷貝到堆內存(HeapByteBuffer)。

FileChannel讀寫文件(非MMAP)

public static void main(String[] args) {        String filename = "小奏技術.txt";        String content = "Hello, 小奏技術.";        // 寫入文件        writeFile(filename, content);        // 讀取文件        System.out.println("Reading from file:");        readFile(filename);    }    public static void writeFile(String filename, String content) {        // 創建文件對象        File file = new File(filename);        // 確保文件存在        if (!file.exists()) {            try {                boolean created = file.createNewFile();                if (!created) {                    System.err.println("Unable to create file: " + filename);                    return;                }            } catch (Exception e) {                System.err.println("An error occurred while creating the file: " + e.getMessage());                return;            }        }        // 使用FileChannel寫入文件        try (RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");             FileChannel fileChannel = randomAccessFile.getChannel()) {            ByteBuffer buffer = ByteBuffer.allocate(content.getBytes().length);            buffer.put(content.getBytes());            buffer.flip(); // 切換到讀模式            while (buffer.hasRemaining()) {                fileChannel.write(buffer);            }        } catch (Exception e) {            System.err.println("An error occurred while writing to the file: " + e.getMessage());        }    }    public static void readFile(String filename) {        // 使用FileChannel讀取文件        try (RandomAccessFile randomAccessFile = new RandomAccessFile(filename, "r");             FileChannel fileChannel = randomAccessFile.getChannel()) {            ByteBuffer buffer = ByteBuffer.allocate((int) fileChannel.size());            while (fileChannel.read(buffer) > 0) {                // Do nothing, just read            }            // 切換到讀模式            buffer.flip();            /* while (buffer.hasRemaining()) {                System.out.print((char) buffer.get());            }*/            Charset charset = StandardCharsets.UTF_8;             String fileContent = charset.decode(buffer).toString();            System.out.print(fileContent);        } catch (Exception e) {            System.err.println("An error occurred while reading the file: " + e.getMessage());        }    }

這里需要注意的一個細節 我們分配的內存的方式是:VG728資訊網——每日最新資訊28at.com

ByteBuffer.allocate()

這里我們可以進入看看源碼:VG728資訊網——每日最新資訊28at.com

圖片圖片VG728資訊網——每日最新資訊28at.com

實際構造的是HeapByteBuffer,也就是JVM的堆內存。VG728資訊網——每日最新資訊28at.com

如果我們使用:VG728資訊網——每日最新資訊28at.com

ByteBuffer.allocateDirect()

圖片圖片VG728資訊網——每日最新資訊28at.com

則構造的是堆外內存DirectByteBuffer。VG728資訊網——每日最新資訊28at.com

HeapByteBuffer和DirectByteBuffer文件讀寫區別

我們看看FileChannel read方法:VG728資訊網——每日最新資訊28at.com

圖片圖片VG728資訊網——每日最新資訊28at.com

發現IO相關的處理被封裝在IOUtil,我們繼續看看IOUtil的write方法:VG728資訊網——每日最新資訊28at.com

圖片圖片VG728資訊網——每日最新資訊28at.com

可以看到如果是DirectBuffer則可以直接寫。如果是HeapByteBuffer則需要轉換為DirectByteBuffer。VG728資訊網——每日最新資訊28at.com

圖片圖片VG728資訊網——每日最新資訊28at.com

為什么要在DirectByteBuffer做一層轉換

主要是HeapByteBuffer受JVM管理,也就是會受到GC影響。如果在進行native調用的時候發生了GC,會導致HeapByteBuffer的內容出現錯誤。具體詳細的說明可以看看這篇MappedByteBuffer VS FileChannel:從內核層面對比兩者的性能差異。講解的非常清晰。VG728資訊網——每日最新資訊28at.com

參考

  • MappedByteBuffer VS FileChannel:從內核層面對比兩者的性能差異 

本文鏈接:http://www.tebozhan.com/showinfo-26-90858-0.htmlJava Nio FileChannel堆內堆外數據讀寫全流程分析及使用

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Wire:Go語言依賴注入的利器

下一篇: 避免鎖表:為Update語句中的Where條件添加索引字段

標簽:
  • 熱門焦點
  • CSS單標簽實現轉轉logo

    轉轉品牌升級后更新了全新的Logo,今天我們用純CSS來實現轉轉的新Logo,為了有一定的挑戰性,這里我們只使用一個標簽實現,將最大化的使用CSS能力完成Logo的繪制與動畫效果。新logo
  • 十個簡單但很有用的Python裝飾器

    裝飾器(Decorators)是Python中一種強大而靈活的功能,用于修改或增強函數或類的行為。裝飾器本質上是一個函數,它接受另一個函數或類作為參數,并返回一個新的函數或類。它們通常用
  • 如何通過Python線程池實現異步編程?

    線程池的概念和基本原理線程池是一種并發處理機制,它可以在程序啟動時創建一組線程,并將它們置于等待任務的狀態。當任務到達時,線程池中的某個線程會被喚醒并執行任務,執行完任
  • 如何使用JavaScript創建一只圖像放大鏡?

    譯者 | 布加迪審校 | 重樓如果您曾經瀏覽過購物網站,可能遇到過圖像放大功能。它可以讓您放大圖像的特定區域,以便瀏覽。結合這個小小的重要功能可以大大改善您網站的用戶體驗
  • 三分鐘白話RocketMQ系列—— 如何發送消息

    我們知道RocketMQ主要分為消息 生產、存儲(消息堆積)、消費 三大塊領域。那接下來,我們白話一下,RocketMQ是如何發送消息的,揭秘消息生產全過程。注意,如果白話中不小心提到相關代
  • 阿里瓴羊One推出背后,零售企業迎數字化新解

    作者:劉曠近年來隨著數字經濟的高速發展,各式各樣的SaaS應用服務更是層出不窮,但本質上SaaS大多局限于單一業務流層面,對用戶核心關切的增長問題等則沒有提供更好的解法。在Saa
  • 認真聊聊東方甄選:如何告別低垂的果實

    來源:山核桃作者:財經無忌爆火一年后,俞敏洪和他的東方甄選依舊是頗受外界關心的“網紅”。7月5日至9日,為期5天的東方甄選“甘肅行”首次在自有App內直播,
  • AMD的AI芯片轉單給三星可能性不大 與臺積電已合作至2nm制程

    據 DIGITIMES 消息,英偉達 AI GPU 出貨逐季飆升,接下來 AMD MI 300 系列將在第 4 季底量產。而半導體業內人士表示,近日傳出 AMD 的 AI 芯片將轉單給
  • 朋友圈可以修改可見范圍了 蘋果用戶可率先體驗

    近日,iOS用戶迎來微信8.0.27正式版更新,除了可更換二維碼背景外,還新增了多項實用功能。在新版微信中,朋友圈終于可以修改可見范圍,簡單來說就是已發布的朋友圈
Top