日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

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

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

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

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

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

一:單個文件下載的管理

1. 單文件下載類層次

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

來一張圖來表示。

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

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

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

2. 單文件下載

對于單個下載,步驟如下

連接資源服務器,獲取資源信息,創(chuàng)建文件

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

1)封裝下載的屬性

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

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

其中包含了4個屬性:

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

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

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

private int priority; //該下載的優(yōu)先級

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

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

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

file.setLength(length);

file.close();

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

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. 創(chuàng)建緩存,創(chuàng)建連接。設置獲取資源數(shù)據(jù)的范圍,創(chuàng)建文件,并設置寫入位置

//創(chuàng)建緩存

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

b= new byte[(int)block.getLength()];elseb= new byte[Constants.BYTES_READ];//創(chuàng)建連接。設置獲取資源數(shù)據(jù)的范圍,從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");//創(chuàng)建RandomAccessFile

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

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

3 .更新block塊的start,以及l(fā)ength,如果length大于0,繼續(xù)進行2,否則則表示當前block已經(jīng)下載完畢,退出該線程。

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){//統(tǒng)計每個block中已經(jīng)下載的段的個數(shù),用于計算當前下載的速度。

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

}

}

in.close();

file.close();

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

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

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

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;//需要統(tǒng)計當前已經(jīng)下載完成段D的數(shù)量。

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()函數(shù)中,計算當前下載的速度

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

Thread.sleep(1000);

checkSpeed();

}

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

總結

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

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