多线程下载
2016-06-24 13:48
323 查看
多线程下载的实现:
1、首先获取文件的长度。
2、设置线程的个数
3、根据长度和线程个数计算每一个线程需要下载的长度。
例如:3个线程下载一个为length=10个字节的文件
int bolckSize=length/3;
则每一部分需要下载的大小为:
线程 1 :int start=0*blockSize int end=1*blockSize-1;
线程 2 :int start=1*blockSize int end=2*blockSize-1;
线程 3 :int start=2*blockSize int end=length-1;//到最后
4、根据RandomAccessFile raf 创建一个同样大小的空文件。
5、设置Http请求的头信息
6、根据raf.seek(int length),把下载好的数据写入空文件的指定位置,拼接成完整的文件。
实现:
用Tomcat作为服务器,服务器目录C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\ROOT下放置了一个guanguan.apk文件。
主界面就一个Button按钮。
运行结果:
1、首先获取文件的长度。
2、设置线程的个数
3、根据长度和线程个数计算每一个线程需要下载的长度。
例如:3个线程下载一个为length=10个字节的文件
int bolckSize=length/3;
则每一部分需要下载的大小为:
线程 1 :int start=0*blockSize int end=1*blockSize-1;
线程 2 :int start=1*blockSize int end=2*blockSize-1;
线程 3 :int start=2*blockSize int end=length-1;//到最后
4、根据RandomAccessFile raf 创建一个同样大小的空文件。
5、设置Http请求的头信息
connection.setRequestProperty("range", "bytes=" + start + "-" + end);
6、根据raf.seek(int length),把下载好的数据写入空文件的指定位置,拼接成完整的文件。
实现:
用Tomcat作为服务器,服务器目录C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\ROOT下放置了一个guanguan.apk文件。
主界面就一个Button按钮。
public class MainActivity extends Activity implements View.OnClickListener { // 要下载文件的路径 private String urlPath = "http://localhost:8080/guanguan.apk"; private String filePath; // 设置线程的数目。 private int threadCount = 3; private Button mButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mButton = (Button) findViewById(R.id.button); mButton.setOnClickListener(this); } @Override public void onClick(View view) { if (view.getId() == R.id.button) { Log.d("dd","开始下载"); new Thread(new GetDataFromNet()).start(); } } //访问网络的类: private class GetDataFromNet implements Runnable { @Override public void run() { try {
//请求网络 URL url = new URL(urlPath); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(5000); // 获取返回值 int code = connection.getResponseCode(); if (code == 200) { // 获取数据总长度 int length = connection.getContentLength(); Log.d("dd","文件长度"+length); // 设置下载位置 filePath = "/sdcard" + "/guanguan.apk"; File file = new File(filePath); Log.d("dd", "下载路径:" + filePath);
// 通过RandomAccessFile创建一个空文件。 rwd 文件权限信息 RandomAccessFile accessFile = new RandomAccessFile(file, "rwd"); // 设置空文件的大小 accessFile.setLength(length); accessFile.close();
//每一段的大小 int bolckSize = length / threadCount;
//计算每个线程下载的起始位置。 for(int i = 0; i < threadCount; i++) { int start = i * bolckSize; int end = (i + 1) * bolckSize - 1;
//如果是最后一个线程,则结束位置为文件的末尾 if (i == (threadCount - 1)) { end = length-1; } Log.d("dd", "第" + i + "个线程" + "从" + start + "到" + end); new DownloadFile(urlPath, filePath, start, end).start(); } } } catch (Exception e) { e.printStackTrace(); } } } }
//文件下载类 public class DownloadFile extends Thread { private String urlPath;//下载路径 private String fileName;//文件保存路径 private int start;//开始位置 private int end;//结束位置 //构造方法 public DownloadFile(String urlPath, String fileName, int start, int end) { this.urlPath = urlPath; this.fileName = fileName; this.start = start; this.end = end; } @Override public void run() { URL url = null; try { url = new URL(urlPath); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(5000);
// 设置Http头的信息,即要指明获取的是那一段数据。
connection.setRequestProperty("range", "bytes=" + start + "-" + end);
int code = connection.getResponseCode();
//注意部分下载返回的code值为 206 if (code == 206) { InputStream is = connection.getInputStream(); File file = new File(fileName);
//创建RandomAccessFile,要与上次已经创建文件名以及权限一致 RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
//该方法用来操作建造好的空文件,可以指明从文件的那个位置开始写入 accessFile.seek(start); byte[] buf = new byte[1024]; int len = 0; while ((len = is.read(buf)) >0) { accessFile.write(buf, 0, len); } is.close(); accessFile.close(); Log.d("dd", "该线程下载了" + start + "--" + end); } } catch (Exception e) { e.printStackTrace(); } } }
运行结果:
相关文章推荐
- Python3写爬虫(四)多线程实现数据爬取
- C#实现多线程的同步方法实例分析
- C#线程间不能调用剪切板的解决方法
- 浅谈chuck-lua中的多线程
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- C#线程同步的三类情景分析
- C#获取进程或线程相关信息的方法
- 简单对比C#程序中的单线程与多线程设计
- C#停止线程的方法
- 解析C#多线程编程中异步多线程的实现及线程池的使用
- C#子线程更新UI控件的方法实例总结
- C#多线程学习之(六)互斥对象用法实例
- C#线程队列用法实例分析
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析
- C#多线程之Thread中Thread.IsAlive属性用法分析
- 分享我在工作中遇到的多线程下导致RCW无法释放的问题