介绍
如何在android项目中使用多线程下载文件?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。
多线程下载文件(支持暂停,取消,断点续传)
多线程同时下载文件即:在同一时间内通过多个线程对同一个请求地址发起多个请求,将需要下载的数据分割成多个部分,同时下载,每个线程只负责下载其中的一部分,最后将每一个线程下载的部分组装起来即可。
涉及的知识及问题
- <李>请求的数据如何分段李> <>李分段完成后如何下载和下载完成后如何组装到一起李> <>李暂停下载和继续下载的实现(wait (), notifyAll(),同步的使用)李> <李>取消下载和断点续传的实现
李,>
首先通过HttpURLConnection请求总文件大小,而后根据线程数计算每一个线程的下载量,在分配给每一个线程去下载
fileLength=conn.getContentLength ();//根据文件大小,先创建一个空文件//皉”——以只读方式打开。调用结果对象的任何写方法都将导致抛出IOException。//皉w”——打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。//耙?匚淦髡尽薄蚩员愣寥『托慈?对于“rw”,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。//皉wd”——打开以便读取和写入,对于“rw”,还要求对文件内容的每个更新都同步写入到底层存储设备。 RandomAccessFile raf=新RandomAccessFile (filePath,“rwd"); raf.setLength (fileLength); raf.close ();//计算各个线程下载的数据段 int blockLength=fileLength/threadCount;
分段完成后给每一个线程的请求头设置范围参数,他允许客户端只请求文件的一部分数据,每一个线程只请求下载相应范围内的数据,使用RandomAccessFile(可随机读写的文件)写入到同一个文件里即可组装成目标文件范围,是在HTTP/1.1里新增的一个头字段,它允许客户端实际上只请求文档的一部分(范围可以相互重叠)
范围的使用形式:
属性解释字节=0 - 499表示头500个字节字节=500 - 999表示第二个500字节字节=-500表示最后500个字节字节=500 -表示500字节以后的范围字节=0 - 0,1第一个和最后一个字节HttpUrlConnection中设置请求头
网址URL=new URL (loadUrl); HttpURLConnection康涅狄格州=(HttpURLConnection) url.openConnection (); conn.setRequestMethod (“GET"); conn.setRequestProperty (“Range",“字节=?+起动位置+“产生绯闻;+ endPosition); conn.setConnectTimeout (5000);//若请求头加上范围这个参数,则返回状态码为206,而不是200 如果(conn.getResponseCode ()==206) { InputStream是=conn.getInputStream (); RandomAccessFile raf=新RandomAccessFile (filePath,“rwd"); raf.seek(起动位置);//跳到指定位置开始写数据 }
关于同步只需记住一下五点:
- <李>当两个并发线程访问同一个对象对象中的这个同步(这)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。李> <李>然而,当一个线程访问对象的一个同步(这)同步代码块时,另一个线程仍然可以访问该对象中的非同步(这)同步代码块。李> <>李尤其关键的是,当一个线程访问对象的一个同步(这)同步代码块时,其他线程对对象中所有其它同步(这)同步代码块的访问将被阻塞。李> <李>第三个例子同样适用其它同步代码块。也就是说,当一个线程访问对象的一个同步(这)同步代码块时,它就获得了这个对象的对象锁。结果,其它线程对该对象对象所有同步代码部分的访问都被暂时阻塞。李> <李>以上规则对其它对象锁同样适用。李>
,((len=is.read(缓冲))!=1){//是否继续下载 如果(! isGoOn) 打破; }
断点续传即其实和重新下载是一样的,不过文件的大小和每一个线程下载时的起始位置和结束位置都不是重新计算的。而是上次取消下载时,每一个线程保存的当前位置和结束位置,让每一个线程接着上次的地方继续下载即可