多线程下载
来源:互联网 发布: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() + "/";}
}
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- 多线程下载
- MyBatis学习 之 一、MyBatis简介与配置MyBatis+Spring+MySql
- 面向数据结构设计的基本思想
- ibatis测试配置sql
- restorecon
- 用JPress创建网站框架
- 多线程下载
- 纯Java的高性能长连接RPC解决方案
- PAT 1023
- js如何准确获取当前页面url网址信息
- JAVA中泛型和集成体系
- 什么时候选择LinkedList?
- 【面试题】剑指offer 16
- C++面试问题——整理篇
- QT5——SpinBox、Double SpinBox 和Slider