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

Java多線程文件分片下載實現(xiàn)的示例代碼

 更新時間:2020年03月06日 08:59:14   作者:qylost  
這篇文章主要介紹了Java多線程文件分片下載實現(xiàn)的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

多線程下載介紹

多線程下載技術(shù)是很常見的一種下載方案,這種方式充分利用了多線程的優(yōu)勢,在同一時間段內(nèi)通過多個線程發(fā)起下載請求,將需要下載的數(shù)據(jù)分割成多個部分,每一個線程只負責下載其中一個部分,然后將下載后的數(shù)據(jù)組裝成完整的數(shù)據(jù)文件,這樣便大大加快了下載效率。常見的下載器,迅雷,QQ旋風等都采用了這種技術(shù)。

分片下載

所謂分片下載就是要利用多線程的優(yōu)勢,將要下載的文件一塊一塊的分配到各個線程中去下載,這樣就極大的提高了下載速度。

技術(shù)難點

并不能說是什么難點,只能說沒接觸過不知道罷了。

1、如何請求才能拿到數(shù)據(jù)的特定部分,而非全部?

可以在HTTP請求頭中加入Range來標識數(shù)據(jù)的請求范圍/區(qū)間,從HTTP/1.1開始可用。

基本用法:

Range: bytes=10-:取第10個字節(jié)及后所有數(shù)據(jù)。

Range: bytes=40-100:取第40個字節(jié)到第100個字節(jié)之間的數(shù)據(jù)。

這樣我們就能拿到特定部分的數(shù)據(jù)了,斷點續(xù)傳也可以用這個來實現(xiàn)。

PS:0為開始點。

2、分片后某線程下載時如何寫出?

思路1:等所有下載完成后進行統(tǒng)一匯總整理然后再一次性寫出。

這簡直是最笨的思路了,如果文件過大全部拉到內(nèi)存中,豈不涼涼。

思路2:下載采用多線程,寫出時采取數(shù)據(jù)前后順序排隊寫出。

也就是說多線程下載,單線程輸出,某種程度解決了內(nèi)存占用問題,不過效率基本不理想。

思路3:要說還是API香,老大哥Java給我們提供了一個類叫做RandomAccessFile。

這個類可以進行隨機文件讀寫,其中有一個seek函數(shù),可以將指針指向任意位置,然后進行讀寫。什么意思呢,舉個栗子:假如我們開了30個線程,首先第一個下載完成的是線程X,它下載的數(shù)據(jù)范圍是4000-9000,那么這時我們調(diào)用seek函數(shù)將指針撥動到4000,然后調(diào)用它的write函數(shù)將byte寫出,這時4000之前都是NULL,4000之后就是我們插入的數(shù)據(jù)。這樣就可以實現(xiàn)多線程下載和本地寫入了。

具體實現(xiàn)

一個分片下載類,我們需要創(chuàng)建多個對象來進行下載。

public class UnitDownloader implements Runnable {
  private int from;
  private int to;
  private File target;
  private String uri;
  private int id;

  public UnitDownloader(int from, int to, File target, String uri, int id) {
    this.from = from;
    this.to = to;
    this.target = target;
    this.uri = uri;
    this.id = id;
  }

  public int getFrom() {
    return from;
  }

  public int getTo() {
    return to;
  }

  @Override
  public void run() {
    //download and save data
    try {
      HttpURLConnection connection = (HttpURLConnection) new URL(uri).openConnection();
      connection.setRequestProperty("Range", "bytes=" + from + "-" + to);
      connection.connect();
      int totalSize = connection.getContentLength();
      InputStream inputStream = connection.getInputStream();
      RandomAccessFile randomAccessFile = new RandomAccessFile(target, "rw");
      randomAccessFile.seek(from);
      byte[] buffer = new byte[1024 * 1024];
      int readCount = inputStream.read(buffer, 0, buffer.length);
      while (readCount > 0) {
        totalSize -= readCount;
        System.out.println("分片:" + this.id + "的剩余:" + totalSize);
        randomAccessFile.write(buffer, 0, readCount);
        readCount = inputStream.read(buffer, 0, buffer.length);
      }
      inputStream.close();
      randomAccessFile.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

分片下載管理器,主要就是拿到內(nèi)容的總大小,將其分配給每一個UnitDownloader。這里的threadCount函數(shù)可以再考慮優(yōu)化一下。

public class MultipleThreadDownloadManager implements Runnable {
  private String uri;
  private File target;

  public MultipleThreadDownloadManager(String uri, File target) {
    this.target = target;
    this.uri = uri;
    if (target.exists() == false) {
      try {
        target.createNewFile();
      } catch (IOException e) {
        e.printStackTrace();
      }
    }
  }

  /**
   * 開始下載
   */
  public void start() {
    new Thread(this).start();
  }


  /**
   * 根據(jù)文件總大小計算線程數(shù)量
   *
   * @param totalSize
   * @return
   */
  public int threadCount(int totalSize) {
    if (totalSize < 30 * 2014 * 1024) {
      return 1;
    }
    return 30;
  }


  @Override
  public void run() {
    //獲取文件總大小
    int totalSize = 0;
    try {
      HttpURLConnection connection = (HttpURLConnection) new URL(uri).openConnection();
      connection.connect();
      int contentLength = connection.getContentLength();
      totalSize = contentLength;
    } catch (IOException e) {
      e.printStackTrace();
    }
    //將文件分片并分開下載
    int threadCount = threadCount(totalSize);
    int perThreadSize = totalSize / threadCount;//每一個線程分到的任務(wù)下載量
    int id = 0;
    int from = 0, to = 0;
    while (totalSize > 0) {
      id++;
      //計算分片
      if (totalSize < perThreadSize) {
        from = 0;
        to = totalSize;
      } else {
        from = totalSize;
        to = from + perThreadSize;
      }
      //開始下載
      UnitDownloader downloader = new UnitDownloader(from, to, target, uri, id);
      new Thread(downloader).start();
    }
  }
}

參考文獻

1、https://emacsist.github.io/2015/12/29/http-%E5%8D%8F%E8%AE%AE%E4%B8%AD%E7%9A%84range%E8%AF%B7%E6%B1%82%E5%A4%B4%E4%BE%8B%E5%AD%90/

2、https://blog.csdn.net/lyt_7cs1dn9/article/details/75105266

到此這篇關(guān)于Java多線程文件分片下載實現(xiàn)的示例代碼的文章就介紹到這了,更多相關(guān)Java多線程分片下載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 通過實例解析spring bean之間的關(guān)系

    通過實例解析spring bean之間的關(guān)系

    這篇文章主要介紹了通過實例解析spring bean之間的關(guān)系,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-01-01
  • Springboot接收前端的Json但是為null問題

    Springboot接收前端的Json但是為null問題

    這篇文章主要介紹了Springboot接收前端的Json但是為null問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教<BR>
    2024-05-05
  • SpringBoot整合Minio實現(xiàn)文件上傳和讀取功能

    SpringBoot整合Minio實現(xiàn)文件上傳和讀取功能

    最近有一個需求是關(guān)于視頻上傳播放的,需要設(shè)計一個方案,中間談到了Minio這個技術(shù),于是來學習一下,所以本文給大家介紹了SpringBoot整合Minio實現(xiàn)文件上傳和讀取功能,文中有詳細的代碼示例供大家參考,需要的朋友可以參考下
    2024-07-07
  • Java?天生就是多線程

    Java?天生就是多線程

    這篇文章主要介紹了Java天生就是多線程,程序天生就是多線程程序,因為執(zhí)行main()方法的是一個名稱為main的線程,更多相關(guān)內(nèi)容需要的小伙伴可以參考一下
    2022-07-07
  • Java 中jasperReport實現(xiàn)動態(tài)列打印的實現(xiàn)代碼

    Java 中jasperReport實現(xiàn)動態(tài)列打印的實現(xiàn)代碼

    這篇文章主要介紹了Java 中jasperReport實現(xiàn)動態(tài)列打印的實現(xiàn)代碼的相關(guān)資料,希望通過本文大家能掌握這部分內(nèi)容,需要的朋友可以參考下
    2017-09-09
  • 一文詳解Elasticsearch和MySQL之間的數(shù)據(jù)同步問題

    一文詳解Elasticsearch和MySQL之間的數(shù)據(jù)同步問題

    Elasticsearch中的數(shù)據(jù)是來自于Mysql數(shù)據(jù)庫的,因此當數(shù)據(jù)庫中的數(shù)據(jù)進行增刪改后,Elasticsearch中的數(shù)據(jù),索引也必須跟著做出改變。本文主要來和大家探討一下Elasticsearch和MySQL之間的數(shù)據(jù)同步問題,感興趣的可以了解一下
    2023-04-04
  • Java?IO流與NIO技術(shù)綜合應(yīng)用詳細實例代碼

    Java?IO流與NIO技術(shù)綜合應(yīng)用詳細實例代碼

    這篇文章主要給大家介紹了關(guān)于Java?IO流與NIO技術(shù)綜合應(yīng)用的相關(guān)資料,文中包括了字節(jié)流和字符流,以及它們的高級特性如緩沖區(qū)、序列化和反序列化,同時還介紹了NIO中的通道和緩沖區(qū),以及選擇器的使用,需要的朋友可以參考下
    2024-12-12
  • SpringBoot常用注解詳細整理

    SpringBoot常用注解詳細整理

    大家好,本篇文章主要講的是SpringBoot常用注解詳細整理,感興趣的同學趕快來看一看吧,對你有幫助的話記得收藏一下,方便下次瀏覽
    2021-12-12
  • Java設(shè)計模式之建造者模式實例詳解

    Java設(shè)計模式之建造者模式實例詳解

    這篇文章主要介紹了Java設(shè)計模式之建造者模式,結(jié)合具體實例形式分析了建造者模式的概念、原理、實現(xiàn)方法與相關(guān)使用注意事項,需要的朋友可以參考下
    2017-09-09
  • Spring加載屬性文件方式(自動加載優(yōu)先級問題)

    Spring加載屬性文件方式(自動加載優(yōu)先級問題)

    這篇文章主要介紹了Spring加載屬性文件方式(自動加載優(yōu)先級問題),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02

最新評論

安塞县| 东源县| 吉木萨尔县| 高阳县| 南通市| 会昌县| 利川市| 包头市| 盘山县| 胶南市| 江阴市| 博客| 泰兴市| 金阳县| 景宁| 油尖旺区| 漯河市| 尉氏县| 青州市| 历史| 阜新市| 阿尔山市| 沂南县| 江西省| 呼玛县| 香河县| 房产| 都江堰市| 福贡县| 西华县| 襄汾县| 白朗县| 武隆县| 舞阳县| 鞍山市| 南充市| 肇东市| 高清| 东方市| 洪湖市| 册亨县|