패키지 cn.me.test;
import java.io.InputStream;
import java.io.RandomAccessFile;
java.net.HttpURLConnection 가져오기;
java.net.URL 가져오기;
/**
*멀티스레드 다운로드
*1: 임의의 위치에 데이터를 쓰려면 RandomAccessFile을 사용하십시오.
*2: 첫 번째 스레드에서 다운로드한 데이터의 양을 계산해야 하며 균등하게 분배할 수 있습니다. 평균이 부족하다면,
* 그러면 마지막 스레드는 상대적으로 작은 데이터를 직접 처리합니다.
*3: 다운로드하기 전에 동일한 크기의 파일을 준비해야 하며 파일 헤더를 통해 얻어야 합니다.
*/
공개 클래스 MultiThreadDownload {
public static void main(String[] args)에서 예외가 발생합니다.
//1: 파일명과 다운로드 주소 선언
문자열 파일명 = "aa.rar";
String urlStr = "http://localhost:7777/day18";
//2: URL 선언
URL url = 새 URL(urlStr+"/"+fileName);
//3: 연결 얻기
HttpURLConnection con=
(HttpURLConnection) url.openConnection();
//4:요청 방법 설정
con.setRequestMethod("GET");
//5: 파일 길이인 요청 헤더를 가져옵니다.
int length = con.getContentLength();//다운로드한 파일의 길이를 가져와서 각 스레드가 다운로드해야 하는 데이터의 양을 계산합니다.
//6: 지정된 디렉터리에 같은 크기의 파일을 생성합니다.
RandomAccessFile file = new RandomAccessFile("d:/a/"+fileName, "rw");//같은 크기의 파일을 생성합니다.
//7: 파일 크기, 자리 표시자 설정
file.setLength(length);//파일 크기를 설정합니다.
파일.닫기();
//8: 스레드 수 정의
정수 크기 = 3;
//9: 각 스레드가 다운로드해야 하는 데이터 바이트 수를 계산합니다. 정확하게 나눌 수 있으면 가장 좋고, 그렇지 않으면 1을 더합니다.
int block = length/size==0?length/size:length/size+1;//각 스레드가 다운로드해야 하는 데이터 양을 계산합니다.
System.err.println("각 스레드는 다운로드해야 합니다: "+block);
//10: 세 개의 스레드를 실행하고 시작하고 끝나는 바이트를 계산합니다.
for(int i=0;i<size;i++){
int start = i*block;
int end = start+(block-1);//각 스레드의 시작 및 끝 바이트를 계산합니다.
System.err.println(i+"="+start+","+end);
new MyDownThread(fileName, start, end,url).start();
}
}
정적 클래스 MyDownThread는 Thread를 확장합니다.
//파일 이름 정의
개인 문자열 파일명;
//다운로드를 시작할 위치 정의
개인 int 시작;
//다운로드할 바이트 정의
비공개 int 끝;
개인 URL URL;
공개 MyDownThread(문자열 파일 이름, int start, int end, URL url){
this.fileName=파일이름;
this.start=시작;
this.end=끝;
this.url=url;
}
@보수
공개 무효 실행() {
노력하다{
//11: 다운로드 시작
HttpURLConnection con=
(HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
//12: 분할된 다운로드에 대한 요청 헤더 설정
con.setRequestProperty("Range","bytes="+start+"-"+end);//서버에서 읽은 파일 블록을 설정합니다.
//13: 다운로드 시작, 판단 필요 206
if(con.getResponseCode()==206){//액세스가 성공하면 반환된 상태 코드는 206입니다.
InputStream in = con.getInputStream();
//14: 임의 쓰기 파일 객체를 선언합니다. rwd는 캐시 영역을 사용하지 않고 즉시 파일에 데이터를 쓰는 것을 의미합니다.
RandomAccessFile out = new RandomAccessFile("d:/a/"+fileName,"rwd");
out.seek(start);//파일의 특정 위치부터 데이터 쓰기를 시작하도록 설정합니다.
바이트[] b=새 바이트[1024];
int len = 0;
while((len=in.read(b))!=-1){
out.write(b,0,len);
}
종료.닫기();
넣다();
}
System.err.println(this.getName()+"실행 완료");
}catch(예외 e){
새로운 RuntimeException(e)을 던져라;
}
}
}
}