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

Java實(shí)現(xiàn)http請(qǐng)求文件流對(duì)帶寬限速獲取md5值

 更新時(shí)間:2025年02月28日 09:45:14   作者:曲奇hmb  
文章介紹了如何在進(jìn)行HTTP請(qǐng)求下載大數(shù)據(jù)時(shí)處理帶寬限制和并發(fā)問(wèn)題,通過(guò)使用緩沖區(qū)和限速邏輯,可以有效控制下載速度,避免掉包和數(shù)據(jù)丟失,核心公式基于帶寬和已下載字節(jié)數(shù)計(jì)算預(yù)期耗時(shí),并通過(guò)Thread.sleep()進(jìn)行動(dòng)態(tài)休眠補(bǔ)償,感興趣的朋友一起看看吧

場(chǎng)景:

當(dāng)進(jìn)行http請(qǐng)求獲取大數(shù)據(jù)的情況,例如下載視頻圖片的情況,特別是云服務(wù)器會(huì)有帶寬限制,超出帶寬會(huì)出現(xiàn)掉包丟數(shù)據(jù)的情況,例如:云服務(wù)器限制25m/s的速度,當(dāng)一個(gè)視頻下載超過(guò)25m/s的速度的時(shí)候就會(huì)導(dǎo)致掉包,除了限速還需要注意下并發(fā)問(wèn)題,多個(gè)線程同時(shí)下載也會(huì)超出帶寬限制,可實(shí)現(xiàn)該代碼并設(shè)置單獨(dú)的線程池,控制同時(shí)并發(fā)的線程數(shù)來(lái)解決帶寬問(wèn)題.

邏輯:

我們可以使用一個(gè)緩沖區(qū),每次從輸入流讀取數(shù)據(jù)后,先將寫(xiě)入文件的同時(shí)更新MD5,這樣更高效,因?yàn)橹恍枰幚硪淮螖?shù)據(jù)。這樣就不會(huì)增加額外的讀取次數(shù),避免影響性能。然后,帶寬限流的邏輯需要確保在限流的同時(shí)處理這兩個(gè)操作。每次讀取數(shù)據(jù)塊后,會(huì)計(jì)算總字節(jié)數(shù)和時(shí)間,判斷是否需要暫停(使用Thread.sleep())。計(jì)算MD5的消耗應(yīng)該相對(duì)較小,主要的時(shí)間還是在網(wǎng)絡(luò)讀取和文件寫(xiě)入上。

1. 核心公式

限速邏輯基于以下公式實(shí)現(xiàn):

預(yù)期耗時(shí)(ms)=已下載總字節(jié)數(shù)×1000最大允許帶寬(B/s)預(yù)期耗時(shí)(ms)=最大允許帶寬(B/s)已下載總字節(jié)數(shù)×1000?

其中 MAX_BPS = NMB/s = N × 1024 × 1024 B/s

2. 控制邏輯分步說(shuō)明

步驟代碼片段說(shuō)明
1. 記錄開(kāi)始時(shí)間long startTime = System.currentTimeMillis();下載任務(wù)啟動(dòng)時(shí)記錄初始時(shí)間戳
2. 累計(jì)下載量totalBytes += bytesRead;每次讀取數(shù)據(jù)塊后更新總字節(jié)數(shù)
3. 計(jì)算理論耗時(shí)expectedTime = (totalBytes * 1000) / MAX_BPS根據(jù)當(dāng)前下載量計(jì)算理論應(yīng)耗時(shí)
4. 對(duì)比實(shí)際耗時(shí)elapsed = now - startTime獲取實(shí)際已耗時(shí)
5. 動(dòng)態(tài)休眠補(bǔ)償Thread.sleep(expectedTime - elapsed)強(qiáng)制等待至理論時(shí)間線

流程:

1. 打開(kāi)網(wǎng)絡(luò)連接,獲取輸入流。

2. 創(chuàng)建文件輸出流和MessageDigest實(shí)例。

3. 循環(huán)讀取數(shù)據(jù)到緩沖區(qū),每次讀取后寫(xiě)入文件,更新MD5(MD5可以邊讀取文件邊計(jì)算,防止整個(gè)文件讀取完再計(jì)算導(dǎo)致的內(nèi)存壓力),并進(jìn)行限流計(jì)算。

4. 下載完成后,關(guān)閉流,并輸出MD5結(jié)果。

實(shí)現(xiàn):

 
public static String getMd5(String url, String type) {
        CloseableHttpClient httpClient = HttpClients.createDefault();
        final long MAX_BPS = 2 * 1024 * 1024; // 200Mbps = 25MB/s
        MessageDigest md;
        // 創(chuàng)建時(shí)間格式化器(線程安全)
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
        try {
            md = MessageDigest.getInstance("MD5");
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5 algorithm not found", e);
        }
        try (CloseableHttpResponse response = httpClient.execute(new HttpGet(url))) {
            HttpEntity entity = response.getEntity();
            if (entity == null) {
                return "";
            }
            // 記錄開(kāi)始時(shí)間
            long startTime = System.currentTimeMillis();
            try (InputStream in = entity.getContent()) {
                byte[] buffer = new byte[8192];
                int bytesRead;
                long totalBytes = 0;
                while ((bytesRead = in.read(buffer)) != -1) {
                    md.update(buffer, 0, bytesRead);
                    totalBytes += bytesRead;
                    // 動(dòng)態(tài)限速邏輯
                    long elapsed = System.currentTimeMillis() - startTime;
                    long expectedTime = (totalBytes * 1000) / MAX_BPS;
                    if (elapsed < expectedTime) {
                        Thread.sleep(expectedTime - elapsed);
                    }
                }
                // 計(jì)算最終統(tǒng)計(jì)信息
                long endTime = System.currentTimeMillis();
                double timeCost = DoubleUtils.formatDouble((endTime - startTime) / 1000.0);
                String sizeMB = String.format("%.3f", DoubleUtils.formatDouble(totalBytes / (1024.0 * 1024)));
                // 生成MD5
                String md5 = DatatypeConverter.printHexBinary(md.digest()).toLowerCase();
                // 完整日志輸出
                log.info("下載完成 | 類型: {} | MD5: {} | 大小: {}MB | 耗時(shí): {}s",
                        type, md5, sizeMB, timeCost);
                return md5;
            }
        } catch (Exception e) {
            // 記錄異常發(fā)生時(shí)間
            String errorTime = LocalDateTime.now().format(formatter);
            log.error("下載失敗 | 類型: {} | 錯(cuò)誤時(shí)間: {} | 原因: {}",
                    type, errorTime, e.getMessage());
            return "";
        }finally {
            try {
                httpClient.close();
            }catch (Exception e) {
            }
        }
    }

到此這篇關(guān)于Java實(shí)現(xiàn)http請(qǐng)求文件流對(duì)帶寬限速獲取md5值的文章就介紹到這了,更多相關(guān)java帶寬限速獲取md5值內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳談Feign的配置類是如何生效的

    詳談Feign的配置類是如何生效的

    這篇文章主要介紹了Feign的配置類是如何生效的,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • SpringBoot Admin之應(yīng)用監(jiān)控與告警配置方式

    SpringBoot Admin之應(yīng)用監(jiān)控與告警配置方式

    這篇文章主要介紹了SpringBoot Admin之應(yīng)用監(jiān)控與告警配置方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-04-04
  • Redisson分布式鎖實(shí)現(xiàn)原理示例詳解

    Redisson分布式鎖實(shí)現(xiàn)原理示例詳解

    Redisson分布式鎖通過(guò)Lua腳本保證原子性操作,實(shí)現(xiàn)了分布式互斥、可重入、自動(dòng)續(xù)期等核心特性,其高級(jí)特性包括公平鎖、讀寫(xiě)鎖和紅鎖算法,能夠滿足不同場(chǎng)景下的并發(fā)控制需求,這篇文章主要介紹了Redisson分布式鎖實(shí)現(xiàn)原理的相關(guān)資料,需要的朋友可以參考下
    2026-04-04
  • 關(guān)于java.lang.NumberFormatException: null的問(wèn)題及解決

    關(guān)于java.lang.NumberFormatException: null的問(wèn)題及解決

    這篇文章主要介紹了關(guān)于java.lang.NumberFormatException: null的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • Spring MVC如何設(shè)置請(qǐng)求頭和響應(yīng)頭的Header

    Spring MVC如何設(shè)置請(qǐng)求頭和響應(yīng)頭的Header

    這篇文章主要介紹了Spring MVC如何設(shè)置請(qǐng)求頭和響應(yīng)頭的Header問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-03-03
  • java8學(xué)習(xí)教程之函數(shù)引用的使用方法

    java8學(xué)習(xí)教程之函數(shù)引用的使用方法

    這篇文章主要給大家介紹了關(guān)于java8學(xué)習(xí)教程之函數(shù)引用的使用,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)下吧。
    2017-09-09
  • 理解HashSet里為什么value不是null

    理解HashSet里為什么value不是null

    你有沒(méi)有想過(guò)Java中HashSet的Value為什么要存PRESENT而不是Null?帶著這個(gè)疑問(wèn)來(lái)看下邊的文章尋找答案吧
    2021-09-09
  • Java notify和notifyAll的區(qū)別和相同

    Java notify和notifyAll的區(qū)別和相同

    本文主要介紹Java notify和notifyAll的知識(shí),這里整理詳細(xì)的資料來(lái)說(shuō)明notify 和NotifAll的區(qū)別,有需要的小伙伴可以參考下
    2016-09-09
  • mybatis實(shí)現(xiàn)批量插入并返回主鍵(xml和注解兩種方法)

    mybatis實(shí)現(xiàn)批量插入并返回主鍵(xml和注解兩種方法)

    這篇文章主要介紹了mybatis實(shí)現(xiàn)批量插入并返回主鍵(xml和注解兩種方法),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Gson序列化指定忽略字段的三種寫(xiě)法詳解

    Gson序列化指定忽略字段的三種寫(xiě)法詳解

    在我們?nèi)粘J褂胘son序列化框架過(guò)程中,經(jīng)常會(huì)遇到在輸出json字符串時(shí),忽略某些字段,那么在Gson框架中,要想實(shí)現(xiàn)這種方式,可以怎么處理呢,本文就來(lái)介紹一下
    2021-10-10

最新評(píng)論

涟水县| 大姚县| 湘乡市| 车致| 普洱| 邹平县| 塘沽区| 广西| 东丰县| 阿克苏市| 博湖县| 成都市| 昌图县| 车致| 普兰店市| 潍坊市| 墨竹工卡县| 新建县| 墨竹工卡县| 乐清市| 北流市| 苗栗市| 巴彦淖尔市| 文登市| 梁山县| 衢州市| 晋州市| 渭源县| 磐安县| 阳城县| 北辰区| 怀远县| 石家庄市| 宝鸡市| 嫩江县| 藁城市| 武宁县| 旺苍县| 博罗县| 广元市| 阿拉善右旗|