多线程

package com.jy.day15installapkmorethreaddownload;

import android.content.Context;
import android.util.Log;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

public class DownLoadMoreThread {
public static String TAG = "DownLoadMoreThread";
public static int thread_count = 5;
public static void httpDownLoadByMoreThreads(
final String apkUrl, final String savePath, final Context context){
ThreadManager.getInstance().execute(new Runnable() {
@Override
public void run() {
//计算每个线程要下载的模块的开始位置和结束位置
try {
URL url= new URL(apkUrl);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
int len = urlConnection.getContentLength();
EventBus.getDefault().post(new MsgE(0,len));//把文件的大小设置给进度条,保存一直,后面通过下载的数据的改变进度
////2.分配任务,5个线程,
//假设 20个数据:0-19
//线程0:0-3,线程1:4-7,线程2:8-11 ,...
int blockSize = len/thread_count;//得到每一个线程要下载的大小 4
//每次for循环计算出本次线程下载的数据的开始和结束位置
for (int i = 0; i < thread_count; i++) {
int start = iblockSize;//开始的位置
int end = (i+1)
blockSize-1;//结束的位置
if(i == thread_count-1){//如果当前是最后一个线程,则下载剩下的所有数据
end = len-1;
}
//启动一个线程进行下载,没有断点
// downThread(i,start,end,apkUrl,savePath,len);
//带断点续传的
downThreadCut(i,start,end,apkUrl,savePath,context,len);
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}

public static void downThread(
        final int i, final int start, final int end, final String apkUrl, final String savePath, final int max) {
        ThreadManager.getInstance().execute(new Runnable() {
        @Override
        public void run() {
            //进行下载
            try {
                URL url= new URL(apkUrl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                ///设置请求部分资源   Range表示随机位置   重点1
                conn.setRequestProperty("Range","bytes="+start+"-"+end); //设置当前线程从start开始  到 end结束
                int responseCode = conn.getResponseCode();
                //HttpURLConnection.HTTP_PARTIAL 是 206,表示允许请求部分数据
                if(responseCode == HttpURLConnection.HTTP_PARTIAL){
                    InputStream inputStream = conn.getInputStream();//得到本线程应该读取的部分数据
                    RandomAccessFile rf = new RandomAccessFile(savePath, "rw");//创建可以读写的随机流  rw表示可读可写
                    rf.seek(start);//把随机流偏移到 应该开始的位置

                    byte[] bytes = new byte[2048];
                    int len = 0;
                    int count = 0;
                    int totalCount = end-start+1;//计算出本线程应该下载的大小
                    while((len = inputStream.read(bytes)) != -1){
                        rf.write(bytes,0,len);
                        count += len;
                        Log.d("MainActivity", "线程:"+i+",totalCount: "+totalCount+
                                ",百分比:"+(float)count/totalCount+",下载大小:"+count);
                        EventBus.getDefault().post(new MsgE(len,max));//把当前下载的长度发出去,Activity接收,显示在进度条上
                    }
                    Log.i("MainActivity", "run: 线程"+i+"下载完毕");
                    inputStream.close();
                    rf.close();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}


public static void downThreadCut(
        final int i, final int start, final int end, final String apkUrl, final String savePath, final Context context, final int max) {
    ThreadManager.getInstance().execute(new Runnable() {
        @Override
        public void run() {
            //进行下载
            try {
                URL url= new URL(apkUrl);
                HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                //得到SharedPreferences保存的本线程上传下载的位置
                int currentPosition = start;  //currentPosition当前下载的开始位置
                int  n = (int) SharedPreferencesUtils.getParam(context, "线程" + i, 0);
                if(n == 0){
                    Log.i("MainActivity", "run: 第一次下载");
                }else {//有值,说明上次下载没有完成,记录了下载到的位置,从此下载
                    currentPosition = n;
                    Log.i("MainActivity", "run:线程"+i+" 接着上次下载,开始位置是:"+currentPosition);
                }
                ///设置请求部分资源   Range表示随机位置
                conn.setRequestProperty("Range","bytes="+currentPosition+"-"+end); //设置当前线程从start开始  到 end结束
                int responseCode = conn.getResponseCode();
                //HttpURLConnection.HTTP_PARTIAL 是 206,表示允许请求部分数据
                if(responseCode == HttpURLConnection.HTTP_PARTIAL){
                    InputStream inputStream = conn.getInputStream();//得到本线程应该读取的部分数据
                    RandomAccessFile rf = new RandomAccessFile(savePath, "rw");//创建可以读写的随机流
                    rf.seek(currentPosition);//把随机流偏移到 应该开始的位置,上次下载写入的位置(下载了一部分)

                    byte[] bytes = new byte[2048];
                    int len = 0;
                    int count = currentPosition-start;//计算出已经下载的大小
                    EventBus.getDefault().post(new MsgE(count,max));//把得到的旧进度,设置到进度条中

// myCallBack.setProgress2(count);//把已经下载的数据量给进度条
int totalCount = end-start+1;//计算出本线程应该下载的大小
while((len = inputStream.read(bytes)) != -1){
rf.write(bytes,0,len);
count += len;//记录下载的大小
currentPosition += len;//把下载位置向前移动len,以为又下载了len长度的数据
Log.d("MainActivity", "线程:"+i+",totalCount: "+totalCount+
",百分比:"+(float)count/totalCount+",下载大小:"+count);
// myCallBack.setProgress2(len);//把新下载的数据量给进度条
//通过SharedPreferencesUtils记录当前下载到的位置,供105行获取使用,供下次下载使用
EventBus.getDefault().post(new MsgE(len,max));//把得到的新进度,设置到进度条中
SharedPreferencesUtils.setParam(context,"线程"+i,currentPosition);
}
//本线程下载完毕,重新设置为0.下回重新下载
SharedPreferencesUtils.setParam(context,"线程"+i,0);
Log.i("MainActivity", "run: 线程"+i+"下载完毕");
inputStream.close();
rf.close();
}

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

}

你可能感兴趣的:(多线程)