【Java】:多线程下载

时间:2021-12-12 12:19:50
 import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection; public class MultithreadsDownload {
public static void main(String[] args) {
final int DOWNLOAD_THREAD_NUM = 4;
final String FILE_NAME = "download.jpg";
InputStream[] is = new InputStream[DOWNLOAD_THREAD_NUM];
RandomAccessFile[] raf = new RandomAccessFile[DOWNLOAD_THREAD_NUM]; try {
URL url = new URL("http://p.qpic.cn/ninja/0/ninja1393807134/0");
for (int i=0; i<DOWNLOAD_THREAD_NUM; i++) {
is[i] = url.openStream();
raf[i] = new RandomAccessFile(FILE_NAME, "rw");
}
long filelen = getFileLength(url);
System.out.println("The size of the file is : " + filelen);
//create a empty final file
for (int i=0; i<filelen; i++)
raf[0].write(0); //compute the download size for per thread
long numPerThread = filelen / DOWNLOAD_THREAD_NUM;
long left = filelen % DOWNLOAD_THREAD_NUM; for (int i=0; i<DOWNLOAD_THREAD_NUM; i++) {
if (i == DOWNLOAD_THREAD_NUM-1)
new DownloadThread(i*numPerThread, (i+1)*numPerThread + left,
is[i], raf[i]).start();
else
new DownloadThread(i*numPerThread, (i+1)*numPerThread,
is[i], raf[i]).start();
}
} catch (Exception e)
{
e.printStackTrace();
}
} public static long getFileLength(URL url) throws Exception
{
URLConnection conn = url.openConnection();
long size = conn.getContentLengthLong();
return size;
}
} class DownloadThread extends Thread { DownloadThread(long start, long end, InputStream is, RandomAccessFile raf)
{
System.out.println("Begin downloading : " + start + "--->" + end);
this.start = start;
this.end = end;
this.is = is;
this.raf = raf;
} @Override
public void run()
{
try {
//seek the appropriate input location of the cur thread
is.skip(start);
//seek the appropriate location for writing
raf.seek(start);
byte[] buff = new byte[BUFF_SIZE];
long contentLen = end - start;
//Ensure the totally download
long times = contentLen / BUFF_SIZE + 4;
int hasRead = 0;
for (int i=0; i<times; i++) {
hasRead = is.read(buff);
if (hasRead < 0)
break;
raf.write(buff, 0, hasRead);
}
} catch (Exception e)
{
e.printStackTrace();
}
finally {
try {
if (is != null)
is.close();
if (raf != null)
raf.close();
}catch (Exception e)
{
e.printStackTrace();
}
}
} private final int BUFF_SIZE = 32;
private long start;
private long end;
private InputStream is;
private RandomAccessFile raf;
}

作用JAVA实现对一个文件的多线程下载,基本思想是先读取文件大小,进行分块,创建多个线程分别负责某一部分的下载任务