Talking about multi-threaded download in Android and Java

Source: Internet
Author: User
Tags ming
<span id="Label3"></p><p><p>Why use multi-threaded download?<br>The reason is a word: "fast", using multi-threaded download faster than a single-threaded download speed, when it comes to download speed, the decision to download the speed of the factors generally have two:<br>One is the actual speed of the client, and the other is the bandwidth of the Server. We often use a single-threaded download, that is, to download a file is to open a thread to request the download of Resources.<br>Here we do not consider the actual client network speed factor, because this factor is changeable, bad Control. The main factor we consider is the bandwidth of the service Side. So how does the server assign each client<br>The download bandwidth of it??? The principle of allocation is that the server only distributes the corresponding download bandwidth evenly to each thread that requests it, which means that each thread enjoys<br>Server-side CPU Time Slice is the same, when one of the threads download time is finished, although its resources are not downloaded, it will have to let the CPU resources to the next thread to use<br>This is actually the principle of the time slice rotation algorithm in the operating system, so its download bandwidth allocation unit is "thread", which is why sometimes we download resources in the process of fast and SLOW.<br>Speaking of which, I believe you generally understand why multithreading is faster than a single-threaded download. If you do not understand, there is no relationship, below I will pass two and an example to illustrate<br>It's the Reason.</p></p><p><p>If we have a scenario such as: Xiao ming, xiaohua, Xiao qiang, They all want to see the same movie xxx.avi, so on the same server to download Xxx.avi. Three people are honest at the Beginning.<br>All only open a thread to request the download resources, this time the server bandwidth assumption is 30M, then according to the allocation principle we said above, three people should average the download speed of 10M.</p></p><p><p></p></p><p><p>But Xiao Ming is really unbearable, he can no longer endure so slow download speed, so he began to consult master, through the Master's guidance, finally acquired the ability of multithreading, so he opened the hanging,<br>Resorted to multi-threaded download of the trick, immediately the other two people are confused forced. How did he do it? While the other two people were downloading, he silently opened two more threads, that is, a total of open<br>Three threads to download the same movie, the server will find, "hey, there are two more threads here, so give them a bit of it." At this point, the server does not know, where three of the threads are from<br>To the same user (note: the Server-side download Bandwidth allocation unit is "thread" rather than "user"). Then the server will be the original 30M bandwidth, now a total of 5 threads, re-evenly distributed again<br>At the end of each thread only 6 m, then xiaoming is very happy, because he opened 3 threads, so he downloaded the movie speed is 18M, and the other two people from the original 10M into the current 6M,<br>It is estimated that the other two people will have to hit the computer, the slower the more slowly, so this is the typical sacrifice of other people's speed to improve their speed example.</p></p><p><p></p></p><p>since, this multi-threaded download so powerful, then the following is explained by Ming Li the mystery of it.<br>2, How to use multi-threaded download??<br>first, we have to say the general idea of multi-threaded download implementation, and the use of multi-threaded download process should be aware of the Problem.<br>Multi-threaded download implementation of the general Idea:<br>The general idea is that the entire file resource is divided into several parts, then several threads are opened and each thread is responsible for downloading the files for each sub-section, because<br>The thread download is asynchronous, greatly shortens the download time, finally writes all the sub-parts to the same file, and finally the reorganization obtains a complete file.<br>First of all, we have to say the entire resource download, we can then get the whole input stream of a file through a network request, and then we need to get an input stream that is not the entire file, but<br>Gets the input stream of the Sub-part file that each thread is responsible for Downloading. Then we get the input stream of the specified size, write it to our local file again, and we need to pay attention when we write the INFLOW.<br>Each sub-part of the input stream must be written to the corresponding file location, otherwise it will cause the input stream in the latter write file to overwrite the input stream written to the file in the previous Section.<br>Once again, we need to be aware of the issues:<br>Question One: How to get the size of the entire download resource<br>Question Two: After obtaining the size of the entire file resource, how to split the file, how to allocate each sub-part file, and let the different sub-threads to download, that is, how to<br>Determines the interval in which each sub-thread downloads a file (that is, the start and end download locations of the sub-section files that each child thread is responsible for Downloading)<br>Question Three: How to get the input stream that we need for the specified size, instead of getting the input stream of the entire file by the service side<br>Question Four: How to make each sub-thread write to the appropriate starting position of the file, and the system by default is every time to write data to the file is written from 0 position, this will appear after<br>Writes data that overwrites the previously written Data.<br>3, one by one to solve the above several problems, to solve these problems, then our multi-threaded also realized<br>Solution to Problem one:<br>Get the entire download resource size, This is very simple, can be directly through the HttpURLConnection network request to get a httpurlconnection type of connection object<br>In the getcontentlength to get the size we need to download the resource File.<br>More importantly: We get this file size to do what??? In fact, to imitate a blank file of the same size to occupy local storage space<br>Why do you do this?? In fact, careful people find that when we download a movie or a file, we will find that in the download directory, a temporary file will appear<br>The temporary file size is the same as the size of the file we want to download, and the file is blank at this Time. You can right-click to view the property file size,<br>Why take up space, we can imagine this scenario, if the computer has only 1 grams of storage space, and you download the movie just 1G, the movie is downloading process<br>If you do not occupy a good space in advance, in the download process you download a song, the space is obviously not enough to install the film, then ask this movie will do?<br>therefore, in order to prevent this situation, there is the so-called pre-occupied storage space.<br>Solution to Problem two:<br>How to split the entire file, because we want each thread to be responsible for each sub-part of the file download task, so directly according to the number of threads, but there is a problem<br>is not able to do each thread evenly allocated each sub-part of the file length, so we take a method, false with N threads, is to let the former n-1 size, the last<br>Include a few remaining pieces, that is, the last thread to process the last remaining subset file Length.<br>So there is the following Formula:<br>Sub-section of the first n-1 thread file size: size=len/threadcount<br>This makes it easy to get the length of each thread responsible for the sub-section file<br>Pseudo Code:<br>int size=length/threadcount;<br>For (int ID = 0; ID < threadcount; id++) {<br>1. Determine the download interval for each thread<br>2, Open the corresponding sub-thread download<br>int Startindex=id*size;//determines The starting position of the sub-section file for each thread<br>int endindex= (id+1) *size-1;//determines The end position of the Sub-part file for each thread<br>If (id==threadcount-1) {//judge if it is the last thread, just let its Sub-part file end position extend last, that is, the file length-1<br>endindex=length-1;<br>}<br>System.out.println ("+id+" Thread download interval is "+startindex+"--"+endindex");<br>Workaround for Issue Three:<br>How do i specify an input stream that determines size? There is a Setrequestproperty method in the HttpURLConnection object to set the header information to get the input stream of the specified size.<br>Conn.setrequestproperty ("Range", "bytes=" +startindex+ "-" +endindex);<br>however, It is important to note that your requested server must support multi-threaded downloads and be able to get the specified size input stream<br>Why do I have to get the input stream of the specified size corresponds to the length of the file, and the resulting input stream corresponding to the specified size is written to the corresponding size Sub-part file by the output stream<br>Workaround for Issue Four:<br>The effect of preventing the default settings (each time you write from 0 Position) overwrites the data that was written earlier, passing through the Seek method in Randomaccessfile to each sub-section file, starting with the<br>location, It also indirectly changes the default to write from 0 each time, from the beginning of each sub-section file, so that the previous data is not Overwritten.<br>Randomaccessfile maccessfile=new randomaccessfile (file, "rwd");//"rwd" readable, writable<br>Maccessfile.seek (startIndex);//means writing a file from a different location<br>By solving the above four problems, the whole realization of the idea of carding a bit, then I will realize the process is roughly summed up to the following 5 points:<br>1, the download resource file size, the same size of the random randomaccessfile blank file, to occupy space<br>2, and divides the Randomaccessfile blank file into several parts, and determines the download space of each sub-part file<br>3. Turn on the corresponding sub-thread<br>4, from the network server to the specified size of the partial input stream<br>5, starting from the different starting position of the Randomaccessfile file to write to which we get the corresponding size of the input stream</p><p><p>Main</p></p><pre code_snippet_id="1704788" snippet_file_name="blog_20160601_1_6653757" class="java" name="code">Package Com.mikyou.multithread;import Java.io.file;import Java.io.randomaccessfile;import Java.net.httpurlconnection;import java.net.malformedurlexception;import java.net.url;/** * @author Zhongqihong * Multi-threaded Download * */public class Main {public static final String path= "http://120.203.56.190:8088/upload/mobilelist.xml";p ublic static int threadcount=3;//the number of threads to download public static void main (string[] Args) {try {url url=new URL (PATH); HttpURLConnection conn= (httpurlconnection) url.openconnection (); conn.setrequestmethod ("GET"); Conn.setconnecttimeout (8000); conn.setreadtimeout (8000); conn.connect (); if (conn.getresponsecode () ==200) {int Length=conn.getcontentlength ();//returns The file Size//occupies file space as a filename =new file ("mobilelist.xml"); Randomaccessfile maccessfile=new randomaccessfile (file, "rwd");//"rwd" readable, writable maccessfile.setlength (length);// Occupy file space int size=length/threadcount;for (int ID = 0; ID < threadcount; id++) {//1, determine download interval per thread//2, open corresponding sub-thread download int Startinde X=id*size;int endindex= (id+1) *size-1;if (id==threadcount-1) {endindex=length-1;} System.out.println ("+id+" Thread Download interval is "+startindex+"--"+endindex"); new downloadthread (startIndex, endIndex, PATH, id) . Start ();}}} Catch (Exception e) {e.printstacktrace ();}}}</pre><p><p><br></p></p><p><p>Downloadthread</p></p><p><p></p></p><pre code_snippet_id="1704788" snippet_file_name="blog_20160601_2_8322197" class="java" name="code">Package Com.mikyou.multithread;import Java.io.bufferedreader;import Java.io.file;import java.io.FileInputStream; Import Java.io.ioexception;import Java.io.inputstream;import Java.io.inputstreamreader;import Java.io.randomaccessfile;import Java.net.httpurlconnection;import Java.net.malformedurlexception;import Java.net.protocolexception;import Java.net.url;public class Downloadthread extends thread{private int startIndex, Endindex,threadid;private String urlstring;public downloadthread (int startindex,int endindex,string urlString,int ThreadId) {this.endindex=endindex;this.startindex=startindex;this.urlstring=urlstring;this.threadid=threadid;} @Overridepublic void Run () {try {url url=new URL (urlstring); HttpURLConnection conn= (httpurlconnection) url.openconnection (); conn.setrequestmethod ("GET"); Conn.setconnecttimeout (8000); conn.setreadtimeout (8000); conn.setrequestproperty ("Range", "bytes=" +startIndex+ "-" +endindex);//set the header information property, get the specified size of the input stream if (conn.getresponsecode () ==206) {//get The specified size byte stream, due to get the portion of the specified largeSmall stream, So the requested code is 206InputStream Is=conn.getinputstream (); File file =new file ("mobilelist.xml"); Randomaccessfile maccessfile=new randomaccessfile (file, "rwd");//"rwd" readable, writable Maccessfile.seek (startIndex);// Represents a file written from a different location byte[] bs=new byte[1024];int len=0;int current=0;while ((len=is.read (bs))!=-1) {maccessfile.write (bs,0, len); current+=len; SYSTEM.OUT.PRINTLN ("+threadid+" thread has downloaded "+current"); Maccessfile.close (); System.out.println ("+threadid+" Thread is downloaded);}} Catch (Exception e) {e.printstacktrace ();} super.run ();}}</pre><p><p><br></p></p><p><p>Operation Result:</p></p><p><p></p></p><p><p>Talking about multi-threaded download in Android and Java</p></p></span>

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.