多线程下载 java_java中多线程下载

这是一个Java实现的多线程断点续传下载程序,通过HTTP连接获取文件并将其分割为多个块,每个块由单独的线程下载。程序会检查本地是否存在已下载的文件部分,如果存在则从上次停止的位置继续下载,确保下载的连续性。当所有线程下载完毕后,删除用于记录下载进度的临时文件。
摘要由CSDN通过智能技术生成

package com.download;

import java.io.File;

import java.io.InputStream;

import java.io.RandomAccessFile;

import java.net.HttpURLConnection;

import java.net.URL;

public class MutileThreadDown {

private static int blockCount=3;

private static int blockSize;

public static void main(String[] args) throws Exception{

String path="http://localhost:8080/Web025Server/media/bootstrap.avi";

URL url=new URL(path);

HttpURLConnection conn=(HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

conn.setConnectTimeout(10000);

conn.setReadTimeout(5000);

int responseCode=conn.getResponseCode();

if(responseCode==200){

int size=conn.getContentLength();

System.out.println("服务器端的长度"+size);

blockSize=size/blockCount;

//创建一个跟服务器端大小相同的空白文件

File file=new File("aa.avi");

RandomAccessFile raf=new RandomAccessFile(file,"rw");

raf.setLength(size);//设置文件的的大小

//2.开启若干个子线程,分别下载资源

for(int i=1;i<=blockCount;i++){

int startIndex=(i-1)*blockSize+0;

int endIndex=i*blockSize-1;

if(i==blockCount){

endIndex=size-1;

}

new DownLoadThread(startIndex, endIndex, i, path).start();;

System.out.println("开启线程"+i+"开始的位置"+startIndex+"结束的位置是"+endIndex);

}

}

conn.disconnect();

}

//定义一个线程的内部类

private static class DownLoadThread extends Thread{

private int startIndex;

private int endIndex;

private int threadi;

private String path;

public DownLoadThread(int startIndex, int endIndex, int threadi,

String path) {

super();

this.startIndex = startIndex;

this.endIndex = endIndex;

this.threadi = threadi;

this.path = path;

}

@Override

public void run() {

try {

String path="http://localhost:8080/Web025Server/media/bootstrap.avi";

URL url=new URL(path);

HttpURLConnection conn=(HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);

conn.setConnectTimeout(10000);

conn.setReadTimeout(5000);

int responseCode=conn.getResponseCode();

System.out.println("服务器的响应码"+responseCode);

//创建一个跟服务器端大小相同的空白文件

File file=new File("aa.avi");

RandomAccessFile raf=new RandomAccessFile(file,"rw");

InputStream in=conn.getInputStream();

raf.seek(startIndex);//从哪个位置开始写文件

int len=-1;

byte[] bytes=new byte[1024];

while((len=in.read(bytes))!=-1){

raf.write(bytes, 0, len);

}

in.close();

raf.close();

} catch (Exception e) {

e.printStackTrace();

}

}

}

}

下面我再贴一下更新后的代码吧,这个可以实现短点下载,关闭程序重新开启后可以继续下载package com.download;

import java.io.BufferedReader;

import java.io.File;

import java.io.FileInputStream;

import java.io.FileOutputStream;

import java.io.InputStream;

import java.io.InputStreamReader;

import java.io.RandomAccessFile;

import java.net.HttpURLConnection;

import java.net.URL;

public class MutileThreadDown {

private static int blockCount=3;//定义需要开启线程的个数

private static int blockSize;

private static int runningThreadCount;//正在运行的线程的数量

public static void main(String[] args) throws Exception{

String path="http://localhost:8080/Web025Server/media/bootstrap.avi";

URL url=new URL(path);

HttpURLConnection conn=(HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

conn.setConnectTimeout(10000);

conn.setReadTimeout(5000);

int responseCode=conn.getResponseCode();

if(responseCode==200){

int size=conn.getContentLength();

System.out.println("服务器端的长度"+size);//服务器端需要下载文件的大小

blockSize=size/blockCount;

//创建一个跟服务器端大小相同的空白文件

File file=new File("aa.avi");

RandomAccessFile raf=new RandomAccessFile(file,"rw");

raf.setLength(size);//设置文件的的大小

//2.开启若干个子线程,分别下载资源

runningThreadCount=blockCount;//刚开始设定正在运行的线程数是线程的总数

for(int i=1;i<=blockCount;i++){

int startIndex=(i-1)*blockSize+0;

int endIndex=i*blockSize-1;

if(i==blockCount){

endIndex=size-1;//最后一个线程需要下载剩下的

}

new DownLoadThread(startIndex, endIndex, i, path).start();;

System.out.println("开启线程"+i+"开始的位置"+startIndex+"结束的位置是"+endIndex);

}

}

conn.disconnect();

}

//定义一个线程的内部类

private static class DownLoadThread extends Thread{

private int startIndex;

private int endIndex;

private int threadi;

private String path;

public DownLoadThread(int startIndex, int endIndex, int threadi,

String path) {

super();

this.startIndex = startIndex;

this.endIndex = endIndex;

this.threadi = threadi;

this.path = path;

}

@Override

public void run() {

try {

//获取当前下载总文件的大小

int total=0;

File filepos=new File(threadi+".txt");//建立一个txt文件记录下载的信息

String path="http://localhost:8080/Web025Server/media/bootstrap.avi";

URL url=new URL(path);

HttpURLConnection conn=(HttpURLConnection) url.openConnection();

conn.setRequestMethod("GET");

//接着从上一次位置下载

if(filepos.exists()&&filepos.length()>0){//判断以前是否下载过

FileInputStream fis=new FileInputStream(filepos);

BufferedReader br=new BufferedReader(new InputStreamReader(fis));

String lasttotalstr=br.readLine();//获取当前线程上一次下载的总大小

int lasttotal=Integer.valueOf(lasttotalstr);

System.out.println("上一次下载的总大小"+lasttotal);

startIndex+=lasttotal;

total+=lasttotal;

fis.close();//很重要

}

conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);

conn.setConnectTimeout(10000);

conn.setReadTimeout(5000);

int responseCode=conn.getResponseCode();

System.out.println("服务器的响应码"+responseCode);

//创建一个跟服务器端大小相同的空白文件

File file=new File("aa.avi");

RandomAccessFile raf=new RandomAccessFile(file,"rw");

InputStream in=conn.getInputStream();

raf.seek(startIndex);//从哪个位置开始写文件

int len=-1;

byte[] bytes=new byte[1024*1024];

while((len=in.read(bytes))!=-1){

RandomAccessFile rf=new RandomAccessFile(filepos, "rwd");

raf.write(bytes, 0, len);

total+=len;

rf.write(String.valueOf(total).getBytes());

rf.close();

}

in.close();

raf.close();

} catch (Exception e) {

e.printStackTrace();

} finally{

synchronized (this) {

runningThreadCount--;

if(runningThreadCount==0){

System.out.println("所有线程下载完毕,可以删除txt记录文件了");//可能会出现线程安全问题

for(int i=1;i<=blockCount;i++){

File f=new File(i+".txt");

boolean b=f.delete();

System.out.println(b);

}

}

}

}

}

}

}

1.得到服务器下载文件的大小,然后在本地设置一个临时文件和服务器端文件大小一致 a)获得访问网络地址 b)通过URL对象的openConnection()方法打开连接,返回一个连接对象 c)设置请求头 i.setRequestMethod ii.setConnectTimeout iii.setReadTimeout d)判断是否响应成功 e)获取文件长度(getContentLength()) f)随机访问文件的读取与写入RandomAccessFile(file, mode) g)设置临时文件与服务器文件大小一致(setLength()) h)关闭临时文件 2.计算出每个线程下载的大小(开始位置,结束位置) a)计算出每个线程下载的大小 b)for循环,计算出每个线程的开始、结束位置 c)最后一个线程处理 3.每创建好一次就要开启线程下载 a)构造方法 b)通过URL对象的openConnection()方法打开连接,返回一个连接对象 c)设置请求头 i.setRequestMethod ii.setConnectTimeout d)判断是否响应成功(206) e)获取每个线程返回的流对象 f)随机访问文件的读取与写入RandomAccessFile(file, mode) g)指定开始位置 h)循环读取 i.保存每个线程下载位置 ii.记录每次下载位置 iii.关闭临时记录位置文件 iv.随机本地文件写入 v.记录已下载大小 i)关闭临时文件 j)关闭输入流 4.为了杀死线程还能继续下载的情况下,从本地文件上读取已经下载文件的开始位置 a)创建保存记录结束位置的文件 b)读取文件 c)将流转换为字符 d)获取记录位置 e)把记录位置赋给开始位置 5.当你的n个线程都下载完毕的时候我进行删除记录下载位置的缓存文件 a)线程下载完就减去 b)当没有正在运行的线程时切文件存在时删除文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值