自己弄的个多线程下载的程序,为什么有时候可以下载完全,有时候会卡在一个地方不动?下载代码如下:
- import java.io.*;
- import java.net.*;
- /*
- 需求:自定义设计多线程下载工具类
- 思路:
- 1,先通过URL对象获取到需下载的内容的地址并连接到指定URL获取文件信息
- 2,计算所需下载文件的大小,并按照需要(线程数)将文件等分
- 3,创建多个线程,每个线程都会负责相应的下载部分(主要利用RandomAccessFile类的任意存储特点)
- 4,进行测试
- */
- public class DownLoad
- {
- //定义下载资源的路径
- private String path;
- //指定下载的文件的保存位置
- private String targetFile;
- //定义需要使用多少个线程下载资源
- private int threadNum;
- //定义下载的线程对象
- private DownThread[] threads;
- //定义文件的总大小
- private long fileSize;
- //定义构造器,初始化资源路径,线程数等字段
- public DownLoad(String path,String targetFile,int threadNum)
- {
- this.path=path;
- this.targetFile=targetFile;
- this.threadNum=threadNum;
- //初始化trheads数组
- threads=new DownThread[threadNum];
- }
- //定义方法,用以获取下载文件的相关信息,并根据线程数将文件进行等分
- public void download()throws Exception
- {
- //定义并初始化指定路径的URL对象
- URL url=new URL(path);
- //通过URL对象获取对指定路径的连接
- HttpURLConnection conn=(HttpURLConnection)url.openConnection();
- //设置连接超时属性
- conn.setConnectTimeout(5*1000);
- //设置连接请求方式
- conn.setRequestMethod("GET");
- //设置请求的接收文件的相关属性
- conn.setRequestProperty("Accept","*/*");
- conn.setRequestProperty("Accept-Language","zh-CN");
- conn.setRequestProperty("Charset","UTF-8");
- conn.setRequestProperty("Connection","Keep-Alive");
- //得到文件的大小
- fileSize=conn.getContentLength();
- conn.disconnect();
- //按线程数将文件等分
- long partSize=fileSize/threadNum+1;
- //使用指定文件创建RandomAccessFile对象
- RandomAccessFile file=new RandomAccessFile(targetFile,"rw");
- //设置本地文件的大小
- file.setLength(fileSize);
- file.close();
- //创建并启动线程
- for(int i=0;i<threadNum;i++)
- {
- //计算每个线程下载的开始位置
- long startPos=i*partSize;
- //每个线程使用一个RandomAccessFile进行下载
- RandomAccessFile part=new RandomAccessFile(targetFile,"rw");
- //设置下载位置
- part.seek(startPos);
- //创建下载线程
- threads[i]=new DownThread(startPos,partSize,part);
- //启动线程
- threads[i].start();
- }
- }
- //定义方法用于获取下载完成的百分比
- public double getComplete()
- {
- //统计所有线程已经下载的大小的总和
- int sumSize=0;
- for(int i=0;i<threadNum;i++)
- {
- sumSize+=threads[i].length;
- }
- //返回已完成的百分比
- return sumSize*1.0/fileSize;
- }
- //测试代码
- public String getCompletes()
- {
- //统计所有线程已经下载的大小的总和
- int sumSize=0;
- for(int i=0;i<threadNum;i++)
- {
- sumSize+=threads[i].length;
- }
- //返回已完成的百分比
- return fileSize+" "+threads[0].length+" "+threads[1].length+" "+threads[2].length+"
- "+threads[3].length+" "+(sumSize*1.0/fileSize);
- }
- //定义内部线程类,用于下载文件
- private class DownThread extends Thread
- {
- //当前线程的下载位置
- private long startPos;
- //定义当前线程负责下载的文件大小
- private long partSize;
- //定义下载用的文件对象
- private RandomAccessFile part;
- //计算已经下载的文件大小
- public long length=0;
- //定义构造器,初始化数据
- public DownThread(long startPos,long partSize,RandomAccessFile part)
- {
- this.startPos=startPos;
- this.partSize=partSize;
- this.part=part;
- }
- //重写run方法
- public void run()
- {
- try
- {
- //定义并初始化指定路径的URL对象
- URL url=new URL(path);
- //通过URL对象获取对指定路径的连接
- HttpURLConnection conn=(HttpURLConnection)url.openConnection();
- //设置连接超时属性
- conn.setConnectTimeout(5*1000);
- //设置连接请求方式
- conn.setRequestMethod("GET");
- //设置请求的接收文件的相关属性
- conn.setRequestProperty("Accept","*/*");
- conn.setRequestProperty("Accept-Language","zh-CN");
- conn.setRequestProperty("Charset","UTF-8");
- //获取文件输入流
- InputStream inStream=conn.getInputStream();
- //跳过startPos个字节(只下载自己负责的部分)
- inStream.skip(startPos);
- //定义字节数组,保存数据
- byte[] buf=new byte[1024];
- int hasRead=0;
- //读取网络数据,并写入本地文件
- while(length<partSize&&(hasRead=inStream.read(buf))!=-1)
- {
- //将数据写入指定文件的指定位置
- part.write(buf,0,hasRead);
- //累计下载的总大小
- length+=hasRead;
- this.yield();
- }
- part.close();
- inStream.close();
- }
- catch(Exception e)
- {
- e.printStackTrace();
- }
- }
- }
- }
复制代码 测试代码如下:
- import java.lang.Math;
- /*
- 测试程序
- */
- public class DownTest
- {
- public static void main(String[] args)throws Exception
- {
- //初始化DownLoad对象
- final DownLoad download=new DownLoad
- ("http://zhangmenshiting.baidu.com/data2/music/57130533/73007331395604861128.mp3?
- xcode=b453c78019aaef462150ccef90c23ba01489e1db000d3934","测试.mp3",4);
- //开始下载
- download.download();
- //定义线程,每过0.1秒统计任务的完成度
- new Thread()
- {
- public void run()
- {
- while(download.getComplete()<1)
- {
- System.out.println("已完成:"+download.getComplete());
- try
- {
- Thread.sleep(1000);
- }
- catch(Exception e){}
- }
- }
- }.start();
- }
- }
复制代码
|