import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class Demo {
public static int threadCount=3;//定义线程的个数
public static int running=3;//正在执行的线程数量是3
public static void main(String[] args) {
String path="http://10.40.238.112:8080/jdk.exe";
try {
URL url=new URL(path);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
if(conn.getResponseCode()==200){
int length=conn.getContentLength();
System.out.println("文件大小="+length);
int blockSize=length/threadCount;//用文件总大小除以线程个数计算得每一下载块的大小
//在本地创建一个和下载文件大小一样的临时文件
RandomAccessFile raf=new RandomAccessFile("jdksetup.exe","rwd");//jdksetup.exe为临时文件的名字,rwd是写入文件的模式,rwd是可读可写
//利用RandomAccessFile类在本地创建一个和下载文件大小一样的临时文件
raf.setLength(length);//为临时文件设置大小
raf.close();//关闭流
//遍历三个线程开始下载
for(int threadId=1;threadId<=threadCount;threadId++){
int startIndex=(threadId-1)*blockSize;//计算每个线程的开始下载位置和结束下载位置
int endIndex=threadId*blockSize-1;
if(threadId==threadCount){//文件大小和线程数量不太可能整除,如果整除不了那么最后一个线程就多下载一点,下载到最后
endIndex=length;
}
System.out.println("线程:"+threadId+"开始:"+startIndex+"结束:"+endIndex);
new DownloadThread(path, threadId, startIndex, endIndex).start();//调用下载方法,注意开启线程
}
}else{
System.out.println("服务器错误");
}
} catch (Exception e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
public static class DownloadThread extends Thread{
private int threadId;//线程的编号
private int startIndex;//每个线程的开始下载位置
private int endIndex;//每个线程的结束下载位置
private String path;//文件在服务器上的位置
//构造方法
public DownloadThread(String path,int threadId, int startIndex, int endIndex) {
this.threadId = threadId;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.path=path;
}
//由于继承了Thread重写run方法
@Override
public void run() {
try {
URL url=new URL(path);
HttpURLConnection conn=(HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5000);
File file=new File(threadId+".txt");
if(file.exists()&&file.length()>0){
FileInputStream fis=new FileInputStream(file);
byte[] buffer=new byte[1024];
int leng=fis.read(buffer);
String length=new String(buffer,0,leng);
int real=Integer.parseInt(length);
startIndex+=real;
fis.close();
}
System.out.println("线程真实下载:"+threadId+"开始:"+startIndex+"结束:"+endIndex);
conn.setRequestProperty("Range","bytes="+startIndex+"-"+endIndex);//从哪开始下载,到哪里结束下载
int code=conn.getResponseCode();
if(code==206){//注意:返回码是200代表是下载的全部,返回码是206代表返回的是下载的文件一部分
InputStream is=conn.getInputStream();
RandomAccessFile raf=new RandomAccessFile("jdk.exe","rwd");
raf.seek(startIndex);//最后把is输出流写入RandomAccessFile中
int len=0;
int total=0;
byte[] buffer=new byte[1024];
while((len=is.read(buffer))!=-1){
raf.write(buffer,0,len);
total+=len;
FileOutputStream fos=new FileOutputStream(threadId+".txt");//实现断点下载
fos.write(String.valueOf(total).getBytes());
fos.close();
}
is.close();
raf.close();
System.out.println(threadId+"线程下载完毕了");
}
} catch (Exception e) {
e.printStackTrace();
}finally{//线程执行完毕销毁保存暂停时创建的文件
running--;
if(running==0){
for(int i=0;i<3;i++){
File file=new File(i+".txt");
file.delete();
}
}
}
}
}
}