1 import java.io.InputStream; 2 import java.io.RandomAccessFile; 3 import java.net.URL; 4 import java.net.URLConnection; 5 6 public class MultithreadsDownload { 7 public static void main(String[] args) { 8 final int DOWNLOAD_THREAD_NUM = 4; 9 final String FILE_NAME = "download.jpg"; 10 InputStream[] is = new InputStream[DOWNLOAD_THREAD_NUM]; 11 RandomAccessFile[] raf = new RandomAccessFile[DOWNLOAD_THREAD_NUM]; 12 13 try { 14 URL url = new URL("http://p.qpic.cn/ninja/0/ninja1393807134/0"); 15 for (int i=0; i<DOWNLOAD_THREAD_NUM; i++) { 16 is[i] = url.openStream(); 17 raf[i] = new RandomAccessFile(FILE_NAME, "rw"); 18 } 19 long filelen = getFileLength(url); 20 System.out.println("The size of the file is : " + filelen); 21 //create a empty final file 22 for (int i=0; i<filelen; i++) 23 raf[0].write(0); 24 25 //compute the download size for per thread 26 long numPerThread = filelen / DOWNLOAD_THREAD_NUM; 27 long left = filelen % DOWNLOAD_THREAD_NUM; 28 29 for (int i=0; i<DOWNLOAD_THREAD_NUM; i++) { 30 if (i == DOWNLOAD_THREAD_NUM-1) 31 new DownloadThread(i*numPerThread, (i+1)*numPerThread + left, 32 is[i], raf[i]).start(); 33 else 34 new DownloadThread(i*numPerThread, (i+1)*numPerThread, 35 is[i], raf[i]).start(); 36 } 37 } catch (Exception e) 38 { 39 e.printStackTrace(); 40 } 41 } 42 43 public static long getFileLength(URL url) throws Exception 44 { 45 URLConnection conn = url.openConnection(); 46 long size = conn.getContentLengthLong(); 47 return size; 48 } 49 } 50 51 class DownloadThread extends Thread { 52 53 DownloadThread(long start, long end, InputStream is, RandomAccessFile raf) 54 { 55 System.out.println("Begin downloading : " + start + "--->" + end); 56 this.start = start; 57 this.end = end; 58 this.is = is; 59 this.raf = raf; 60 } 61 62 @Override 63 public void run() 64 { 65 try { 66 //seek the appropriate input location of the cur thread 67 is.skip(start); 68 //seek the appropriate location for writing 69 raf.seek(start); 70 byte[] buff = new byte[BUFF_SIZE]; 71 long contentLen = end - start; 72 //Ensure the totally download 73 long times = contentLen / BUFF_SIZE + 4; 74 int hasRead = 0; 75 for (int i=0; i<times; i++) { 76 hasRead = is.read(buff); 77 if (hasRead < 0) 78 break; 79 raf.write(buff, 0, hasRead); 80 } 81 } catch (Exception e) 82 { 83 e.printStackTrace(); 84 } 85 finally { 86 try { 87 if (is != null) 88 is.close(); 89 if (raf != null) 90 raf.close(); 91 }catch (Exception e) 92 { 93 e.printStackTrace(); 94 } 95 } 96 } 97 98 private final int BUFF_SIZE = 32; 99 private long start; 100 private long end; 101 private InputStream is; 102 private RandomAccessFile raf; 103 }
作用JAVA实现对一个文件的多线程下载,基本思想是先读取文件大小,进行分块,创建多个线程分别负责某一部分的下载任务