亚洲精品久久久中文字幕-亚洲精品久久片久久-亚洲精品久久青草-亚洲精品久久婷婷爱久久婷婷-亚洲精品久久午夜香蕉

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

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

瀏覽:100日期:2022-09-04 18:54:27

多線程下載介紹

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

分片下載

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

技術(shù)難點(diǎn)

并不能說(shuō)是什么難點(diǎn),只能說(shuō)沒(méi)接觸過(guò)不知道罷了。

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

可以在HTTP請(qǐng)求頭中加入Range來(lái)標(biāo)識(shí)數(shù)據(jù)的請(qǐng)求范圍/區(qū)間,從HTTP/1.1開(kāi)始可用。

基本用法:

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

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

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

PS:0為開(kāi)始點(diǎn)。

2、分片后某線程下載時(shí)如何寫(xiě)出?

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

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

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

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

思路3:要說(shuō)還是API香,老大哥Java給我們提供了一個(gè)類(lèi)叫做RandomAccessFile。

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

具體實(shí)現(xiàn)

一個(gè)分片下載類(lèi),我們需要?jiǎng)?chuàng)建多個(gè)對(duì)象來(lái)進(jìn)行下載。

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)容的總大小,將其分配給每一個(gè)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(); } } } /** * 開(kāi)始下載 */ public void start() { new Thread(this).start(); } /** * 根據(jù)文件總大小計(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(); } //將文件分片并分開(kāi)下載 int threadCount = threadCount(totalSize); int perThreadSize = totalSize / threadCount;//每一個(gè)線程分到的任務(wù)下載量 int id = 0; int from = 0, to = 0; while (totalSize > 0) { id++; //計(jì)算分片 if (totalSize < perThreadSize) {from = 0;to = totalSize; } else {from = totalSize;to = from + perThreadSize; } //開(kāi)始下載 UnitDownloader downloader = new UnitDownloader(from, to, target, uri, id); new Thread(downloader).start(); } }}

參考文獻(xiàn)

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多線程文件分片下載實(shí)現(xiàn)的示例代碼的文章就介紹到這了,更多相關(guān)Java多線程分片下載內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 亚欧日韩毛片在线看免费网站 | 亚洲精品无线乱码一区 | 久久国产精品视频一区 | 久久91亚洲人成电影网站 | 欧美黄色性视频 | 午夜精品一区二区三区在线观看 | 国产美女极品免费视频 | 香蕉视频精品 | 国产chinesehdxxxx大胸 | 一级特黄a 大片免费 | 中日韩黄色大片 | 国产成人啪午夜精品网站男同 | 91国偷自产一区二区三区蜜臀 | 久久人人插 | 一级特黄毛片 | 亚洲免费精品 | 一区二区三区久久精品 | 国产高清大尺度一区二区不卡 | 久久国产成人 | 99久久精品无码一区二区毛片 | 免费高清欧美一区二区视频 | 免费亚洲一区 | 成年人黄色大全 | 日本黄色免费网址 | 九九这里只有精品视频 | 午夜精品成人毛片 | 尤物视频网站在线 | 最近最新中文字幕免费的一页 | 国产女人性做爰视频 | 婷婷激情在线视频 | 欧美色片在线观看 | 国产成人啪一区二区 | 亚洲黄色网址大全 | 日韩第一页在线观看 | 国产主播大尺度精品福利 | 韩国一级特黄毛片大 | 丁香婷婷综合五月六月 | 亚洲邪恶 | 欧美日韩一区二区视频免费看 | 国产精品乱 | 亚洲精品永久www嫩草 |