用Java实现的多线程下载类,后面会加入gui和断点续传之类的功能改进为一个较为完善的Java程序。
代码如下:
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.*;
public class t {
public static void main(String[] args) throws IOException {
URL url = new URL("http://baiduliulanqi.00791.com/style/images/img-1-1.png");
URLConnection urlConnection = url.openConnection();
int contentLength = urlConnection.getContentLength();
System.out.println(contentLength);
RandomAccessFile file = new RandomAccessFile("/Users/caohao/IdeaProjects/threadlearn/src/main/resources/targetfile.png","rw");
file.setLength(contentLength);
file.close();
int concurrentThreadSize=4;//设置为四个线程同时下载
int threadFileSize = contentLength/concurrentThreadSize+1;//每个线程块所负责的大小
for (int i = 0; i < concurrentThreadSize; i++) {
FIleDownLoader fIleDownLoader = new FIleDownLoader(i * threadFileSize, threadFileSize, "http://baiduliulanqi.00791.com/style/images/img-1-1.png");
new Thread(fIleDownLoader).start();
}
}
}
class FIleDownLoader implements Runnable{
private int order;//所负责文件块的第一个下标
private RandomAccessFile concurrentFileBlock;//所负责的文件
private int fileSize;//所负责的总大小
String url;//url
private int nowFileSize=0;//当前所完成的大小
public FIleDownLoader(){
}
public FIleDownLoader(int order, int fileSize,String url) {
this.order = order;
this.concurrentFileBlock = concurrentFileBlock;
this.fileSize = fileSize;
this.url=url;
}
@Override
public void run() {
try {
URL url = new URL(this.url);
URLConnection connection = url.openConnection();
connection.setConnectTimeout(1000);
InputStream inputStream = connection.getInputStream();
inputStream.skip(order);
concurrentFileBlock = new RandomAccessFile("/Users/caohao/IdeaProjects/threadlearn/src/main/resources/targetfile.png","rw");
concurrentFileBlock.seek(order);
byte[] buffer = new byte[1024];
int hashRead = 0;
while (nowFileSize<fileSize&&(hashRead=inputStream.read(buffer))!=-1){
concurrentFileBlock.write(buffer,0,hashRead);
nowFileSize+=hashRead;
}
concurrentFileBlock.close();
inputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
大致的思路就是,通过URLconnection来建立连接并按照线程个数对目标文件进行分配。