多线程下载文件—代码优化

来源:互联网 发布:midi制作软件app 编辑:程序博客网 时间:2024/06/05 22:59

启动多线程下载线程:

private void downloadApk(){new downloadTask().start();}

downloadTask:

//xlh_add 多线程下载public class downloadTask extends Thread {private long blockSize,downloadSizeMore;private int threadNum = 5;public downloadTask(){}@Overridepublic void run() {Looper.prepare();FileDownloadThread[] fds = new FileDownloadThread[threadNum+1];try {if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){String sdpath = Environment.getExternalStorageDirectory() + "/";mSavePath = sdpath + "qipotv";File file = new File(mSavePath);if (!file.exists()){file.mkdir();}File apkFile = new File(mSavePath, mHashMap.get("name").trim());Log.v("xulongheng*apkFile", "*"+apkFile.getPath());apkFile.createNewFile();URL url = new URL(mHashMap.get("url"));HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.connect();//获取下载文件的总大小fileSize =conn.getContentLength();Log.v("xulongheng*fileSize",fileSize+"*");//计算每个线程要下载的数据量blockSize = fileSize / threadNum;// 解决整除后百分比计算误差downloadSizeMore =(fileSize % threadNum);//File file = new File(fileName);for (int i = 0; i< threadNum; i++) {//启动线程,分别下载自己需要下载的部分FileDownloadThread fdt =new FileDownloadThread(url, apkFile,i * blockSize, (i + 1)* blockSize - 1);fdt.setName("Thread"+ i);fdt.start();fds[i] =fdt;}if(downloadSizeMore>0){FileDownloadThread fdt =new FileDownloadThread(url, apkFile,(threadNum) * blockSize, fileSize);fdt.setName("Thread"+ threadNum);fds[threadNum] =fdt;fdt.start();}boolean finished = false;while (!finished) {//// 先把整除的余数搞定//downloadedSize =downloadSizeMore;finished = true;downloadedSize=0;for (int i = 0; i< fds.length; i++) {downloadedSize +=fds[i].getDownloadSize();Log.v("xulongheng*downloadedSize", downloadedSize+"*");if (!fds[i].isFinished()){finished = false;}}//当收到更新视图消息时,计算已完成下载百分比,同时更新进度条信息progress = (int)(downloadedSize* 100L /fileSize) ;//(Double.valueOf((downloadedSize* 1.0 /fileSize * 100))).intValue();Log.v("xulongheng*progress", progress+"*");//通知handler去更新视图组件mHandler.sendEmptyMessage(DOWNLOAD);//handler.sendEmptyMessageDelayed(DOWNLOAD, 1000);Log.v("xulongheng*finished", finished+"*");if(finished){mHandler.sendEmptyMessage(DOWNLOAD_FINISH);break;}}}} catch(Exception e) {}Looper.loop();}}
多线程中单个线程类:

package com.qipo.util;import java.io.BufferedInputStream;import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;import java.net.URL;import java.net.URLConnection;import android.util.Log;public class FileDownloadThread extends Thread{private static final int BUFFER_SIZE=1024;private URL url;private File file;private long startPosition;private long endPosition;private long curPosition;//用于标识当前线程是否下载完成private boolean finished=false;private int downloadSize=0;public FileDownloadThread(URL url,File file,long startPosition,long endPosition){this.url=url;this.file=file;this.startPosition=startPosition;this.curPosition=startPosition;this.endPosition=endPosition;}@Overridepublic void run() {BufferedInputStream bis = null;RandomAccessFile fos =null; byte[] buf = new byte[BUFFER_SIZE];URLConnection con =null;try {con =url.openConnection();con.setAllowUserInteraction(true);//设置当前线程下载的起点,终点con.setRequestProperty("Range","bytes="+ startPosition + "-"+ endPosition);//使用java中的RandomAccessFile对文件进行随机读写操作fos = new RandomAccessFile(file, "rw");//设置开始写文件的位置fos.seek(startPosition);bis = new BufferedInputStream(con.getInputStream()); //开始循环以流的形式读写文件while (curPosition < endPosition) {int len =bis.read(buf, 0,BUFFER_SIZE); if (len <0) {break;}if(curPosition + len<endPosition){fos.write(buf, 0, len);downloadSize+=len;}else{fos.write(buf, 0, (int)(endPosition-curPosition));downloadSize+=(endPosition-curPosition);}//fos.write(buf, 0, len);curPosition =curPosition + len;//if (curPosition > endPosition) {//downloadSize+=len- (curPosition - endPosition) + 1;//} else{//downloadSize+=len;//}}//下载完成设为truethis.finished = true;bis.close();fos.close();} catch(IOException e) {Log.d(getName() +"Error:",e.getMessage());}}public boolean isFinished(){return finished;}public synchronized long  getDownloadSize(){return downloadSize;}}