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

java管道piped輸入流與輸出流應(yīng)用場(chǎng)景案例分析

 更新時(shí)間:2022年02月21日 11:11:00   作者:kl  
這篇文章主要介紹了java管道流PipedInputStream與PipedOutputStream(輸入流與輸出流)的應(yīng)用場(chǎng)景案例分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步

前言

PipedInputStream 和 PipedOutputStream 設(shè)計(jì)用來解決跨線程的字節(jié)數(shù)據(jù)傳輸。它們總是成對(duì)出現(xiàn)的,而在使用上,也只能 工作在兩個(gè)不同的線程上,在一個(gè)線程里使用管道輸入和輸出流可能會(huì)造成死鎖。網(wǎng)上有很多介紹這兩個(gè)存在于 io 包下的 api。卻幾乎 找不到一個(gè)寫 PipedInputStream 的使用場(chǎng)景的,所以本文結(jié)合實(shí)際業(yè)務(wù),來聊一聊 PipedInputStream 的應(yīng)用。

原理簡(jiǎn)介

我們知道,輸出流寫數(shù)據(jù),輸入流讀數(shù)據(jù),PipedInputStream 和 PipedOutputStream 也一樣,在 PipedOutputStream 的內(nèi)部有一個(gè) PipedInputStream 類型的 sink屬性,用來接收 PipedOutputStream 寫入的字節(jié)數(shù)據(jù)。

而在 PipedInputStream 內(nèi)部,定義了一個(gè)默認(rèn)為 1024 大小的字節(jié)數(shù)組 buffer,作為數(shù)據(jù)傳輸?shù)木彌_區(qū)。這樣一來,就變成了 PipedOutputStream 往 buffer 里寫數(shù)據(jù),當(dāng)寫滿了 buffer 時(shí),便使用 notifyAll() 喚醒讀數(shù)據(jù)的線程可以讀數(shù)據(jù)了,然后阻塞 1s 后繼續(xù)嘗試寫數(shù)據(jù)。

PipedInputStream 從 buffer 里讀數(shù)據(jù),當(dāng)數(shù)據(jù)讀完 buffer 為空時(shí),便 notifyAll() 喚醒寫的線程可以寫數(shù)據(jù)了,然后阻塞 1s 后繼續(xù)嘗試讀數(shù)據(jù)。

PipedOutputStream 端數(shù)據(jù)寫完后,調(diào)用 close() 方法,會(huì)標(biāo)記 PipedInputStream 里的 closedByWriter=true。此時(shí),從 buffer 讀取數(shù)據(jù),會(huì)返回 -1。標(biāo)識(shí)了數(shù)據(jù)讀完到達(dá)了流的末尾了。

使用場(chǎng)景概述

public static void main(String[] args) {
        try (PipedOutputStream out = new PipedOutputStream();
             PipedInputStream in = new PipedInputStream(out)) {
            new Thread(() -> {
                try {
                    out.write("hello kl".getBytes(StandardCharsets.UTF_8));
                    out.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
            int receive;
            while ((receive = in.read()) != -1) {
                System.err.print((char) receive);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

上面代碼演示了,在一個(gè)線程里寫數(shù)據(jù),然后在 main 線程讀數(shù)據(jù)的場(chǎng)景,完成了跨線程的數(shù)據(jù)傳輸。寫到這里,都挺干巴巴的,很多人看了后肯定也不知道它到底能干啥,有啥作用,繼續(xù)往下看。

實(shí)際應(yīng)用

簡(jiǎn)單的理解了原理后,寫了一個(gè)簡(jiǎn)單的演示 demo,但是 demo 不能說明啥問題,那從一個(gè)線程傳輸字節(jié)到另一個(gè)線程到底有啥用呢?博主,簡(jiǎn)單的的總結(jié)下:通過 java 應(yīng)用生成文件,然后需要將文件上傳到云端的場(chǎng)景,都可以用管道流。相同的業(yè)務(wù)場(chǎng)景,在沒了解管道流之前,都是先將文件寫入到本地磁盤,然后從文件磁盤讀出來上傳到云盤。了解這個(gè)后,可以腦補(bǔ)出很多的業(yè)務(wù)場(chǎng)景了(真實(shí)業(yè)務(wù)場(chǎng)景,都是博主遇到過的),比如:

案例一:EXCEL 文件導(dǎo)出功能

之前有一個(gè)文件導(dǎo)出的功能,但是因?yàn)?,?dǎo)出的文件比較大,導(dǎo)出下載完的時(shí)間非常長,所以,設(shè)計(jì)成了,頁面點(diǎn)擊導(dǎo)出后,后臺(tái)觸發(fā)導(dǎo)出任務(wù),然后將mysql 中的數(shù)據(jù)根據(jù)導(dǎo)出條件查詢出來,生成 Excel文件,然后將文件上傳到 oss,最后像觸發(fā)導(dǎo)出任務(wù)的人的釘釘發(fā)一個(gè)下載文件的鏈接。之前的做法,正如上面所言,先將文件寫到本地,然后從本地目錄讀出來上傳到 oss,下面演示下管道流一步到位的方式:

public static void main(String[] args) {
        try (PipedOutputStream out = new PipedOutputStream();
             PipedInputStream in = new PipedInputStream(out)) {
            new Thread(() -> {
                Listdatabase = new LinkedList<>();
                try {
                    //文件生成
                    ExcelUtils.getInstance().exportObjects2Excel(database,out);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
            //文件上傳
            ossClient.putObject("test","test.xlsx",in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

案例二:XML 文件數(shù)據(jù)傳輸

此類需求常見于和銀行以及金融機(jī)構(gòu)對(duì)接時(shí),要求上報(bào)一些 xml 格式的數(shù)據(jù),給到指定的 ftp、或是 oss 的某個(gè)目錄下,用于對(duì)賬。其實(shí)從文件上傳的場(chǎng)景來說,和上面的案例一是一樣。也是我總結(jié)的那樣,在內(nèi)存里生成文件,然后上傳到云端,偽代碼如下:

public static void main(String[] args) {
        try (PipedOutputStream out = new PipedOutputStream();
             PipedInputStream in = new PipedInputStream(out)) {
            new Thread(() -> {
                Listdatabase = new LinkedList<>();
                try(GZIPOutputStream gzipOut = new GZIPOutputStream(out)) {
                    Marshaller marshaller = JAXBContext.newInstance(Object.class).createMarshaller();
                    marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
                    marshaller.marshal(database,gzipOut);
                } catch (IOException | JAXBException e) {
                    e.printStackTrace();
                }
            }).start();
            //文件上傳
            ossClient.putObject("test","test.xml.gz",in);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

總體來說,和案例一沒啥區(qū)別,只是案例二多了一步壓縮操作,最終上傳的文件是一個(gè) gzip 的壓縮包,壓縮包內(nèi)是 xml 文件。用這種方式可以大大減少文件的體積、提升上傳的速度

結(jié)語

PipedInputStream 和 PipedOutputStream 設(shè)計(jì)用來解決跨線程的字節(jié)數(shù)據(jù)傳輸。在實(shí)際業(yè)務(wù)需求中,當(dāng)需要在內(nèi)存中生成文件然后上傳到云端時(shí),請(qǐng)記得使用管道流

以上就是java管道piped輸入流與輸出流應(yīng)用場(chǎng)景案例分析的詳細(xì)內(nèi)容,更多關(guān)于java管道piped輸入流與輸出流應(yīng)用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java throw Exception實(shí)現(xiàn)異常轉(zhuǎn)換

    Java throw Exception實(shí)現(xiàn)異常轉(zhuǎn)換

    這篇文章主要介紹了Java throw Exception實(shí)現(xiàn)異常轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-04-04
  • 海量數(shù)據(jù)去重排序bitmap(位圖法)在java中實(shí)現(xiàn)的兩種方法

    海量數(shù)據(jù)去重排序bitmap(位圖法)在java中實(shí)現(xiàn)的兩種方法

    今天小編就為大家分享一篇關(guān)于海量數(shù)據(jù)去重排序bitmap(位圖法)在java中實(shí)現(xiàn)的兩種方法,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-02-02
  • Java圖書管理系統(tǒng)課程設(shè)計(jì)

    Java圖書管理系統(tǒng)課程設(shè)計(jì)

    這篇文章主要為大家詳細(xì)介紹了Java圖書管理系統(tǒng)課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • java解析.yml文件方式

    java解析.yml文件方式

    這篇文章主要介紹了java解析.yml文件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • ?Spring?中?Bean?的生命周期詳解

    ?Spring?中?Bean?的生命周期詳解

    這篇文章主要介紹了Spring中Bean的生命周期詳解,Java中的公共類稱之為Bean或Java?Bean,而Spring中的Bean指的是將對(duì)象的生命周期
    2022-09-09
  • datatables 帶查詢條件java服務(wù)端分頁處理實(shí)例

    datatables 帶查詢條件java服務(wù)端分頁處理實(shí)例

    本篇文章主要介紹了datatables 帶查詢條件java服務(wù)端分頁處理實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-06-06
  • Java中@Async異步失效的9種場(chǎng)景

    Java中@Async異步失效的9種場(chǎng)景

    最近在項(xiàng)目某個(gè)方法使用@Async注解,但是該方法還是同步執(zhí)行了,異步不起作用,到底是什么原因呢?接下來本文給大家介紹了Java?@Async異步失效的9種場(chǎng)景,需要的朋友可以參考下
    2024-05-05
  • Java實(shí)現(xiàn)計(jì)算一個(gè)月有多少天和多少周

    Java實(shí)現(xiàn)計(jì)算一個(gè)月有多少天和多少周

    這篇文章主要介紹了Java實(shí)現(xiàn)計(jì)算一個(gè)月有多少天和多少周,本文直接給出實(shí)例代碼,需要的朋友可以參考下
    2015-06-06
  • 使用Sentinel滑動(dòng)窗口實(shí)現(xiàn)限流和降級(jí)

    使用Sentinel滑動(dòng)窗口實(shí)現(xiàn)限流和降級(jí)

    Sentinel 是一個(gè)開源的高可用性、高擴(kuò)展性的實(shí)時(shí)流量控制框架,它可以用于保護(hù)服務(wù)穩(wěn)定性,防止系統(tǒng)因?yàn)榱髁窟^大而崩潰,這篇文章我們所介紹的是滑動(dòng)窗口,它是 Sentinel 實(shí)現(xiàn)限流和降級(jí)的重要組件之一,感興趣的同學(xué)跟著小編來看看吧
    2023-09-09
  • Spring中Cache的使用方法詳解

    Spring中Cache的使用方法詳解

    這篇文章主要介紹了Spring中Cache的使用方法詳解,Spring Cache 是一個(gè)框架,實(shí)現(xiàn)了基于注解的緩存功能,只需要簡(jiǎn)單地加一個(gè)注解,就能實(shí)現(xiàn)緩存功能,Spring Cache 提供了一層抽象,底層可以切換不同的緩存實(shí)現(xiàn),需要的朋友可以參考下
    2024-01-01

最新評(píng)論