Java多线程下载
来源:互联网 发布:下载识谱软件 编辑:程序博客网 时间:2024/06/07 17:00
最近在做一个简单的多线程下载,记录下遇到的难题
主要思路
- 下载之前需要创建一个同等大小的空文件来占取储存空间
- 每个线程只下载一部分资源,如果有2个线程,则第一个线程下载前面一半,第二个线程下载后一半
- 将每个线程获取的资源,按资源顺序写入目标文件
- 最后一个线程下载完后,主线程通知用户下载完成
类介绍
java.io.RandomAccessFile
提供对文件的读写功能,与普通的输入输出流不一样的是RamdomAccessFile
可以任意的访问文件的任何地方。
//以读写方式打开指定文件,不存在就创建新文件。RandomAccessFile randomAccessFile = new RandomAccessFile(“data.temp”,"rw");//设置data.temp文件的大小randomAccessFile.setLength(1024);//设置读取或写入的开始位置randomAccessFile.seek(0);
java.net.HttpURLConnection
//设置访问资源的范围 如果设置了Range 则 response code=206 (部分连接)httpURLConnection.setRequestProperty("Range","bytes="+startPos+"-"+endPos);//获取链接成功返回的数据InputStream inputStream = httpURLConnection.getInputStream();
java.util.concurrent.CountDownLatch
CountDownLatch
是通过一个计数器来实现的,计数器的初始值为线程的数量。每当一个线程完成了自己的某一指定目标,计数器的值就会减1,然后该线程继续执行。如我们创建3个下载线程,主线程中就需要等待3个下载线程完成后再通知用户下载完成。而每个子线程下载完成(目标),先让计数器减去1,然后该干嘛干嘛去,不需要等其他下载线程。
//3表示需要等待的线程个数CountDownLatch countDownLatch = new CountDownLatch(3);//获取未完成线程的个数countDownLatch.getCount();//等待线程个数减去1countDownLatch.countDown();//等待计数器等于0,再执行后面的代码countDownLatch.await();
具体代码
FileDownloader
import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;import java.util.concurrent.CountDownLatch;public class FileDownloader { private String address; public FileDownloader(String address) { this.address = address; } public void download(int threadCount) { try { URL url = new URL(address); HttpURLConnection httpURLConnection = (HttpURLConnection) url .openConnection(); int length = httpURLConnection.getContentLength(); System.out.println("文件大小:"+length); // 写死了,没有从Header中获取文件类型,以及文件名 File file = new File("E:\\download.jpg"); RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw"); randomAccessFile.setLength(length); randomAccessFile.close(); CountDownLatch countDownLatch = new CountDownLatch(threadCount); // 计算每个线程下载的数据大小 int blockSize = length / threadCount; for (int i = 0; i < threadCount; i++) { int startPos = blockSize * i; int endPos = blockSize * (i + 1); if (i == threadCount - 1) { endPos = length; } new DownloadThread(file, countDownLatch, address, startPos, endPos - 1).start(); } while (countDownLatch.getCount() != 0) { System.out.println("下载中...."); try { // 休眠 Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("下载完成"); } catch (IOException e) { e.printStackTrace(); } }}
DownloadThread
import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;import java.util.concurrent.CountDownLatch;public class DownloadThread extends Thread { private File file; private CountDownLatch countDownLatch; private String address; private int startPos; private int endPos; public DownloadThread(File file, CountDownLatch countDownLatch, String address, int startPos, int endPos) { super(); this.file = file; this.countDownLatch = countDownLatch; this.address = address; this.startPos = startPos; this.endPos = endPos; } public void run() { Thread current = Thread.currentThread(); System.out.println(current.getName() + "开始下载:" + startPos + "-" + endPos); RandomAccessFile randomAccessFile = null; InputStream inputStream = null; try { URL url = new URL(address); HttpURLConnection httpURLConnection = (HttpURLConnection) url .openConnection(); httpURLConnection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); inputStream = httpURLConnection.getInputStream(); randomAccessFile = new RandomAccessFile(file, "rw"); randomAccessFile.seek(startPos); byte[] bytes = new byte[1024]; int read = 0; while ((read = inputStream.read(bytes)) != -1) { randomAccessFile.write(bytes, 0, read); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (randomAccessFile != null) { randomAccessFile.close(); } if (inputStream != null) { inputStream.close(); } } catch (IOException e) { e.printStackTrace(); } System.out.println(current.getName() + "下载完成"); countDownLatch.countDown(); } }}
DownloadTest
public class DownloadTest { public static void main(String[] args) { String url = "http://7xq43s.com1.z0.glb.clouddn.com/yunanding-6.jpg";//3.82M FileDownloader fileDownloader = new FileDownloader(url); fileDownloader.download(3); }}
输出
文件大小:4013554Thread-0开始下载:0-1337850Thread-1开始下载:1337851-2675701下载中....Thread-2开始下载:2675702-4013553下载中....下载中....下载中....下载中....下载中....下载中....下载中....下载中....下载中....下载中....下载中....下载中....Thread-1下载完成下载中....Thread-0下载完成下载中....下载中....下载中....Thread-2下载完成下载完成
本人对线程的理解还不够深入,如有错误,恳请指出,感激不尽
0 0
- java 多线程下载
- java 多线程断点下载
- Java多线程下载
- java多线程下载
- java多线程下载
- Java多线程下载
- java多线程下载
- Java多线程下载
- java多线程下载程序
- Java多线程下载文件
- java多线程下载文件
- java实现多线程下载
- Java多线程下载
- Java多线程下载文件
- java多线程下载
- Java多线程下载文件
- Java多线程下载文件
- Java多线程下载代码
- tp5 model 使用
- mysql源码安装
- protobuf2.6.1安装问题
- 《ACM程序设计》书中题目--problem k
- jquery之extend解析
- Java多线程下载
- Tomcat关于网络的基础
- Linux学习
- Notification通知栏的用法
- QT之GUI学习笔记(三)——API文档的使用
- 【机房重构】——存储过程
- MATLAB图像处理第一节
- Android 自定义控件的属性使用
- Oracle的数据库管理(一)——逻辑备份与恢复