多线程下载

来源:互联网 发布:unity3d怎么做建筑 编辑:程序博客网 时间:2024/06/03 18:32

package com.itheima.muchdown_android;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import android.os.Bundle;
import android.os.Environment;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast;

public class MainActivity extends Activity implements OnClickListener{

private EditText et_threadCount;private Context mContext;private LinearLayout ll_progress_layout;private  int threadCount = 0;//开启3个线程private  int blockSize = 0;//每个线程下载的大小private  int runningTrheadCount = 0;//当前运行的线程数private  String path = "http://192.168.13.83:8080/1.mp4";private Map<Integer,ProgressBar> map = new HashMap<Integer, ProgressBar>();@Overrideprotected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    mContext = this;    findViewById(R.id.bt_download).setOnClickListener(this);    ll_progress_layout = (LinearLayout) findViewById(R.id.ll_progress_layout);    et_threadCount = (EditText) findViewById(R.id.et_threadCount);}@Overridepublic void onClick(View v) {    //获取用户输入的线程数    String threadCount_str = et_threadCount.getText().toString().trim();    threadCount = Integer.parseInt(threadCount_str);    //清空控件中的所有子控件    ll_progress_layout.removeAllViews();    //根据线程数添加相应数量的ProgressBar    for(int i =0 ;i < threadCount;i++ ){        ProgressBar progressbar = (ProgressBar) View.inflate(mContext, R.layout.child_progressbar_layout, null);        map.put(i, progressbar);//将ProgressBar放到map中,方便在线程中获取并设置进度        //child: 子控件         ll_progress_layout.addView(progressbar);    }    new Thread(new Runnable() {        @Override        public void run() {            download();        }    }).start();}private void download() {    try{        //1.请求url地址获取服务端资源的大小        URL url = new URL(path);        HttpURLConnection openConnection = (HttpURLConnection) url.openConnection();        openConnection.setRequestMethod("GET");        openConnection.setConnectTimeout(10*1000);        int code = openConnection.getResponseCode();        if(code == 200){            //获取资源的大小            int filelength = openConnection.getContentLength();            //2.在本地创建一个与服务端资源同样大小的一个文件(占位)            RandomAccessFile randomAccessFile = new RandomAccessFile(new File(getFileName(path)), "rw");            randomAccessFile.setLength(filelength);//设置随机访问文件的大小            //3.要分配每个线程下载文件的开始位置和结束位置。            blockSize = filelength/threadCount;//计算出每个线程理论下载大小            for(int threadId =0 ;threadId < threadCount;threadId++){                int startIndex =  threadId * blockSize;//计算每个线程下载的开始位置                int endIndex = (threadId+1)*blockSize -1;//计算每个线程下载的结束位置                //如果是最后一个线程,结束位置需要单独计算                if(threadId == threadCount-1){                    endIndex = filelength -1;                }                //4.开启线程去执行下载                new DownloadThread(threadId, startIndex, endIndex).start();            }        }    }catch (Exception e) {        e.printStackTrace();    }}public  class DownloadThread  extends Thread{    private int threadId;    private int startIndex;    private int endIndex;    private int lastPostion;    private int currentThreadTotalProgress;    public DownloadThread(int threadId,int startIndex,int endIndex){        this.threadId = threadId;        this.startIndex = startIndex;        this.endIndex = endIndex;        this.currentThreadTotalProgress = endIndex -startIndex +1;    }    @Override    public void run() {        //获取当前线程对应ProgressBar        ProgressBar progressBar = map.get(threadId);        synchronized (DownloadThread.class) {            runningTrheadCount = runningTrheadCount +1;//开启一线程,线程数加1        }        //分段请求网络连接,分段保存文件到本地        try{            URL url = new URL(path);            HttpURLConnection openConnection = (HttpURLConnection) url.openConnection();            openConnection.setRequestMethod("GET");            openConnection.setConnectTimeout(10*1000);            System.out.println("理论上下载:  线程:"+threadId+",开始位置:"+startIndex+";结束位置:"+endIndex);            //读取上次下载结束的位置,本次从这个位置开始直接下载。

// File file2 = new File(getFilePath()+threadId+”.txt”);

            if(SharedUtils.getLastPosition(mContext, threadId) != -1){                /*          BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(file2)));                String lastPostion_str = bufferedReader.readLine();                lastPostion = Integer.parseInt(lastPostion_str);//读取文件获取上次下载的位置                 */                                 lastPostion =  SharedUtils.getLastPosition(mContext, threadId);                //说明该线程已经下载完成                if(lastPostion == endIndex+1){                    progressBar.setProgress(currentThreadTotalProgress);                    runningTrheadCount = runningTrheadCount -1;                }                //设置分段下载的头信息。  Range:做分段数据请求用的。                openConnection.setRequestProperty("Range", "bytes:"+lastPostion+"-"+endIndex);//bytes:0-500:请求服务器资源中0-500之间的字节信息  501-1000:                System.out.println("实际下载:  线程:"+threadId+",开始位置:"+lastPostion+";结束位置:"+endIndex);

// bufferedReader.close();
}else{

                lastPostion = startIndex;                //设置分段下载的头信息。  Range:做分段数据请求用的。                openConnection.setRequestProperty("Range", "bytes:"+lastPostion+"-"+endIndex);//bytes:0-500:请求服务器资源中0-500之间的字节信息  501-1000:                System.out.println("实际下载:  线程:"+threadId+",开始位置:"+lastPostion+";结束位置:"+endIndex);            }            if(openConnection.getResponseCode() == 206){//200:请求全部资源成功, 206代表部分资源请求成功                InputStream inputStream = openConnection.getInputStream();                //请求成功将流写入本地文件中,已经创建的占位那个文件中                RandomAccessFile randomAccessFile = new RandomAccessFile(new File(getFileName(path)), "rw");                randomAccessFile.seek(lastPostion);//设置随机文件从哪个位置开始写。                //将流中的数据写入文件                byte[] buffer = new byte[1024*100];                int length = -1;                int total = 0;//记录本次线程下载的总大小                while((length= inputStream.read(buffer)) !=-1){                    randomAccessFile.write(buffer, 0, length);                    total = total+ length;                    //去保存当前线程下载的位置,保存到文件中                    int currentThreadPostion = lastPostion + total;//计算出当前线程本次下载的位置                    /*//创建随机文件保存当前线程下载的位置                    File file = new File(getFilePath()+threadId+".txt");                    RandomAccessFile accessfile = new RandomAccessFile(file, "rwd");                    accessfile.write(String.valueOf(currentThreadPostion).getBytes());                    accessfile.close();*/                    SharedUtils.setLastPosition(mContext, threadId, currentThreadPostion);                    //计算线程下载的进度并设置进度                    int currentprogress = currentThreadPostion -startIndex;                    progressBar.setMax(currentThreadTotalProgress);//设置进度条的最大值                    progressBar.setProgress(currentprogress);//设置进度条当前进度                }                //关闭相关的流信息                inputStream.close();                randomAccessFile.close();                System.out.println("线程:"+threadId+",下载完毕");                //当所有线程下载结束,删除存放下载位置的文件。                synchronized (DownloadThread.class) {                    runningTrheadCount = runningTrheadCount -1;//标志着一个线程下载结束。                    if(runningTrheadCount == 0 ){                        runOnUiThread(new Runnable() {                            @Override                            public void run() {                                Toast.makeText(mContext, "下载完毕", 0).show();                            }                        });                        System.out.println("所有线程下载完成");                        for(int i =0 ;i< threadCount;i++){                            File file = new File(getFilePath()+i+".txt");                            System.out.println(file.getAbsolutePath());                            file.delete();                        }                    }                }            }        }catch (Exception e) {            e.printStackTrace();        }        super.run();    }}public  String getFileName(String url){    return  Environment.getExternalStorageDirectory() + "/"+ url.substring(url.lastIndexOf("/"));}public String getFilePath(){    return Environment.getExternalStorageDirectory() + "/";}

}

0 0
原创粉丝点击