日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java 多线程下载器_Java多线程的下载器(1)

發布時間:2025/3/20 java 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 多线程下载器_Java多线程的下载器(1) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

實現了一個基于Java多線程的下載器,可提供的功能有:

1. 對文件使用多線程下載,并顯示每時刻的下載速度。

2. 對多個下載進行管理,包括線程調度,內存管理等。

一:單個文件下載的管理

1. 單文件下載類層次

首先簡要介紹一下單個文件下載管理的類層次:

來一張圖來表示。

為需要下載的文件創建一個Download類,Download負責管理該文件下載時的線程管理、文件管理、當前速度計算等操作。

根據線程的數目tNum,將該文件分為tNum段,每段為一個DownloadBlock。在實際下載的過程中,并不是一次把所有的東西下載完,而是每次下載固定size的一段Di。所以每個DownloadBlock又會分成n段。

為每個DownloadBlock申請一個線程DownloadThread。其主要作用就是每次下載一段Di,并將其寫入到文件中。

2. 單文件下載

對于單個下載,步驟如下

連接資源服務器,獲取資源信息,創建文件

切分資源,為每個線程分配固定的下載區域。

1)封裝下載的屬性

在建立下載之前,我們把每一次下載進行抽象封裝。

首先把URL、目標文件等封裝在一個DownloadConfig類中。

其中包含了4個屬性:

private URL url; //文件下載地址

private File file; //下載文件保存目標文件

private int nthread; //下載該文件需要的線程數

private int priority; //該下載的優先級

2)連接資源服務器,獲取資源信息,創建文件,并指定文件大小

length =config.getUrl().openConnection().getContentLength();

RandomAccessFilefile= new RandomAccessFile(config.getFile(), "rw"); //隨機讀取

file.setLength(length);

file.close();

3)切分資源,為每個線程分配固定的下載區域,并將當前的下載加入到隊列中

int size = length /config.getNthread();for(int i = 0; i < config.getNthread(); i++){int start = i *size;intlen;if(i == config.getNthread() - 1)

len= length -start;else len =size;//并將當前的下載加入到下載隊列中

addDownloadBlock(getDownloadBlock(start, len));

}

3)啟動線程進行下載

下載的步驟如下:

1. 創建緩存,創建連接。設置獲取資源數據的范圍,創建文件,并設置寫入位置

//創建緩存

byte[] b;if(block.getLength()

b= new byte[(int)block.getLength()];elseb= new byte[Constants.BYTES_READ];//創建連接。設置獲取資源數據的范圍,從startPos到endPos

URLConnection con = null;

con.setRequestProperty("Range", "bytes=" + block.getStart() + "-" + block.getStart()+block.getLength()-1);

RandomAccessFile file= new RandomAccessFile(block.getDownload().getConfig().getFile(), "rw");//創建RandomAccessFile

file.seek(block.getStart()); //從startPos開始寫入

2. 如果當前block的length大于0,則從URL資源處獲取固定大小的資源,并將其寫入到文件中。

3 .更新block塊的start,以及length,如果length大于0,繼續進行2,否則則表示當前block已經下載完畢,退出該線程。

InputStream in =block.getDownload().getConfig().getUrl().openStream();intn;//對該block內的文件進行下載,

while(count

long newLength = (block.getLength() - count) / 2;long newStart = block.getStart() + block.getLength() -newLength;

DownloadBlock newBlock=block.getDownload().getDownloadBlock(newStart, newLength);

block.setLength(block.getLength()-newLength);

block.getDownload().addDownloadBlock(newBlock);

}//寫入文件

n =in.read(b);if(n < 0){break;

}else if(count + n >block.getLength()){

file.write(b,0, (int)(block.getLength() -count));

count=block.getLength();

}else{

count+=n;

file.write(b,0, n);

}//set block count in download

if(n > 0){//統計每個block中已經下載的段的個數,用于計算當前下載的速度。

block.getDownload().setBlockCount(block.getStart(), count);

}

}

in.close();

file.close();

二 . 當前文件下載速度與進度計算

如第一個圖所表示的,每個Block中又分為了很多的段D1、D2、…Dn,因此當為 了計算當前下載的速度,需要將下載的段D的數量統計出來,這里使用了一個ConcurrentHashMap來保存每個block已經下載完成的段D的數目。其中key為每個block的start值,而value為該block已經下載完的段 D。

在當前時刻,我們需要統計當前Download已經下載完成段D的數量,然后再和上一時刻的相比較,則可以得出當前的下載速度。具體代碼見下:

class CheckSpeedTask extendsTimerTask{private static final Log log = LogFactory.getLog(CheckSpeedTask.class);privateDownload download;private ConcurrentHashMapblockCounts;private long speed = 0; //Byte/S

private long count = 0; //Total downloaded byte count

private long lastCount = 0;private long time = 0; //Check time

private long lastTime = 0;public CheckSpeedTask(Download download, long startTime, ConcurrentHashMapblockCounts){this.download =download;this.lastTime =startTime;this.blockCounts =blockCounts;

}

@Overridepublic voidrun() {try{

time=System.currentTimeMillis();

count= 0;//需要統計當前已經下載完成段D的數量。

for(longc : blockCounts.values()){

count+=c;

}

speed= (count -lastCount)/((time - lastTime)/1000);

log.debug(blockCounts.size()+ " threads are downloading " + download + ", cuttent is " + speed + "Byte/S, " + (count * 1.0)/download.getLength()*100 + "% downloaded");

download.setCount(count);

download.setSpeed(speed);

lastTime=time;

lastCount=count;

}catch(Exception e) {//TODO: handle exception

e.printStackTrace();

}

}

}

這樣我們就可以在Thread類的run()函數中,計算當前下載的速度

while(activeThreads.size() > 0 || blockQueue.size() > 0){

Thread.sleep(1000);

checkSpeed();

}

原文:http://blog.csdn.net/zhzhl202/article/details/7521377

總結

以上是生活随笔為你收集整理的java 多线程下载器_Java多线程的下载器(1)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。