pacote cn.me.test;
importar java.io.InputStream;
importar java.io.RandomAccessFile;
importar java.net.HttpURLConnection;
importar java.net.URL;
/**
* Download multithread
*1: Use RandomAccessFile para gravar dados em qualquer local.
*2: A quantidade de dados baixados pelo primeiro thread precisa ser calculada e pode ser distribuída uniformemente. Se não for médio o suficiente,
* Em seguida, o último thread processa diretamente dados relativamente pequenos
*3: Arquivos do mesmo tamanho devem ser preparados antes do download e obtidos através do cabeçalho do arquivo
*/
classe pública MultiThreadDownload {
public static void main(String[] args) lança exceção {
//1: Declara o nome do arquivo e o endereço de download
String nomeArquivo = "aa.rar";
String urlStr = "http://localhost:7777/day18";
//2: Declarar URL
URL url = nova URL(urlStr+"/"+nomeArquivo);
//3: Obtenha a conexão
HttpURLConexão con=
(HttpURLConnection) url.openConnection();
//4: Defina o método de solicitação
con.setRequestMethod("OBTER");
//5: Obtenha o cabeçalho da solicitação, que é o comprimento do arquivo
int length = con.getContentLength();//Obtém o comprimento do arquivo baixado para calcular a quantidade de dados que cada thread deve baixar.
//6: Cria um arquivo do mesmo tamanho no diretório especificado
RandomAccessFile file = new RandomAccessFile("d:/a/"+fileName, "rw");//Cria um arquivo do mesmo tamanho.
//7: Definir tamanho do arquivo, espaço reservado
file.setLength(comprimento); //Define o tamanho do arquivo.
arquivo.close();
//8: Defina o número de threads
tamanho interno = 3;
//9: Calcule quantos bytes de dados cada thread deve baixar. Se for exatamente divisível, é melhor, caso contrário, adicione 1.
int block = length/size==0?length/size:length/size+1;//Calcula a quantidade de dados que cada thread deve baixar.
System.err.println("Cada thread deve baixar: "+block);
//10: Execute três threads e calcule qual byte começa e termina
for(int i=0;i<tamanho;i++){
int início = i*bloco;
int end = start+(block-1); //Calcula os bytes inicial e final de cada thread.
System.err.println(i+"="+start+","+end);
new MyDownThread(nomedoarquivo, início, fim,url).start();
}
}
classe estática MyDownThread estende Thread{
//Define o nome do arquivo
private String nomeArquivo;
//Define onde iniciar o download
início interno privado;
//Define para qual byte baixar
fim interno privado;
URL URL privado;
public MyDownThread(String nomeArquivo,int início,int fim,URL url){
this.fileName = nomedoarquivo;
isto.start=início;
isto.end=fim;
isto.url=url;
}
@Substituir
execução void pública() {
tentar{
//11: Iniciar o download
HttpURLConexão con=
(HttpURLConnection) url.openConnection();
con.setRequestMethod("OBTER");
//12: Defina o cabeçalho da solicitação para downloads segmentados
con.setRequestProperty("Range","bytes="+start+"-"+end);//Define os blocos de arquivos lidos do servidor.
//13: Comece o download, preciso julgar 206
if(con.getResponseCode()==206){//O acesso foi bem-sucedido, o código de status retornado é 206.
InputStream in = con.getInputStream();
//14: Declare um objeto de arquivo de gravação aleatório. Observe que rwd se refere à gravação de dados no arquivo imediatamente, sem usar a área de cache.
RandomAccessFile out = new RandomAccessFile("d:/a/"+fileName,"rwd");
out.seek(start);//Definido para começar a gravar dados de uma determinada posição no arquivo.
byte[] b=novo byte[1024];
int len=0;
while((len=in.read(b))!=-1){
out.write(b,0,len);
}
out.close();
in.close();
}
System.err.println(this.getName()+"Execução concluída");
}catch(Exceção e){
lançar nova RuntimeException(e);
}
}
}
}