使用ApacheHttpClient实现多线程下载的小例子 thrift client 多线程

原帖:http://zywang.iteye.com/blog/916489

网上类似的文章很多,参考了很多人的,大部分人都是用URLConnection写的。

使用ApacheHttpClient实现多线程下载的小例子 thrift client 多线程

原理一:HTTP多线程下载原理

1、发送一个含有Rang头的Head请求,如果返回状态码为206,则允许多线程下载

原理二:多线程下载原理

1、使用HttpClient的Head请求获取请求文件的信息

2、发送一个Rang的Head请求判断是否允许多线程下载

3、通过主任务创建多个分段下载线程,分段下载文件,然后用Java的随机读写文件类保存下载的内容

等有时间了再添加内容吧,先简单写这么多

调度功能代码片段

Java代码 0)contentLength = Long.valueOf(headers[0].getValue());httpHead.abort(); httpHead = new HttpHead(url);httpHead.addHeader("Range", "bytes=0-"+(contentLength-1)); response= httpClient.execute(httpHead);if(response.getStatusLine().getStatusCode() == 206){ acceptRanges =true; } httpHead.abort(); } private void startDownloadThread()throws IOException, FileNotFoundException { //创建下载文件 File file =new File(localPath); file.createNewFile(); RandomAccessFile raf =new RandomAccessFile(file, "rw"); raf.setLength(contentLength);raf.close(); //定义下载线程事件实现类 DownloadThreadListener listener = newDownloadThreadListener() { public voidafterPerDown(DownloadThreadEvent event) { //下载完一个片段后追加已下载字节数synchronized (object) { DownloadTask.this.receivedCount +=event.getCount(); } } public void downCompleted(DownloadThreadEventevent) { //下载线程执行完毕后从主任务中移除 threads.remove(event.getTarget());if(getDebug()){ System.out.println("剩余线程数:"+threads.size()); } } };//不支持多线程下载时 if (!acceptRanges) { if(getDebug()){System.out.println("该地址不支持多线程下载"); } //定义普通下载 DownloadThread thread= new DownloadThread(url, 0, contentLength, file, false);thread.addDownloadListener(listener); thread.start();threads.add(thread); return; } //每个请求的大小 long perThreadLength =contentLength / threadCount + 1; long startPosition = 0; longendPosition = perThreadLength; //循环创建多个下载线程 do{ if(endPosition>= contentLength) endPosition = contentLength - 1;DownloadThread thread = new DownloadThread(url, startPosition,endPosition, file); thread.addDownloadListener(listener);thread.start(); threads.add(thread); startPosition = endPosition +1;//此处加 1,从结束位置的下一个地方开始请求 endPosition += perThreadLength; } while(startPosition < contentLength); }" quality="high"allowscriptaccess="always" type="application/x-shockwave-flash"pluginspage="http://www.macromedia.com/go/getflashplayer">
  1. publicvoidstartDown()throwsException{
  2. HttpClienthttpClient=newDefaultHttpClient();
  3. try{
  4. //获取下载文件信息
  5. getDownloadFileInfo(httpClient);
  6. //启动多个下载线程
  7. startDownloadThread();
  8. //开始监视下载数据
  9. monitor();
  10. }catch(Exceptione){
  11. throwe;
  12. }finally{
  13. httpClient.getConnectionManager().shutdown();
  14. }
  15. }
  16. privatevoidgetDownloadFileInfo(HttpClienthttpClient)throwsIOException,
  17. ClientProtocolException,Exception{
  18. HttpHeadhttpHead=newHttpHead(url);
  19. HttpResponseresponse=httpClient.execute(httpHead);
  20. //获取HTTP状态码
  21. intstatusCode=response.getStatusLine().getStatusCode();
  22. if(statusCode!=200)thrownewException("资源不存在!");
  23. if(getDebug()){
  24. for(Headerheader:response.getAllHeaders()){
  25. System.out.println(header.getName()+":"+header.getValue());
  26. }
  27. }
  28. //Content-Length
  29. Header[]headers=response.getHeaders("Content-Length");
  30. if(headers.length>0)
  31. contentLength=Long.valueOf(headers[0].getValue());
  32. httpHead.abort();
  33. httpHead=newHttpHead(url);
  34. httpHead.addHeader("Range","bytes=0-"+(contentLength-1));
  35. response=httpClient.execute(httpHead);
  36. if(response.getStatusLine().getStatusCode()==206){
  37. acceptRanges=true;
  38. }
  39. httpHead.abort();
  40. }
  41. privatevoidstartDownloadThread()throwsIOException,
  42. FileNotFoundException{
  43. //创建下载文件
  44. Filefile=newFile(localPath);
  45. file.createNewFile();
  46. RandomAccessFileraf=newRandomAccessFile(file,"rw");
  47. raf.setLength(contentLength);
  48. raf.close();
  49. //定义下载线程事件实现类
  50. DownloadThreadListenerlistener=newDownloadThreadListener(){
  51. publicvoidafterPerDown(DownloadThreadEventevent){
  52. //下载完一个片段后追加已下载字节数
  53. synchronized(object){
  54. DownloadTask.this.receivedCount+=event.getCount();
  55. }
  56. }
  57. publicvoiddownCompleted(DownloadThreadEventevent){
  58. //下载线程执行完毕后从主任务中移除
  59. threads.remove(event.getTarget());
  60. if(getDebug()){
  61. System.out.println("剩余线程数:"+threads.size());
  62. }
  63. }
  64. };
  65. //不支持多线程下载时
  66. if(!acceptRanges){
  67. if(getDebug()){
  68. System.out.println("该地址不支持多线程下载");
  69. }
  70. //定义普通下载
  71. DownloadThreadthread=newDownloadThread(url,0,contentLength,file,false);
  72. thread.addDownloadListener(listener);
  73. thread.start();
  74. threads.add(thread);
  75. return;
  76. }
  77. //每个请求的大小
  78. longperThreadLength=contentLength/threadCount+1;
  79. longstartPosition=0;
  80. longendPosition=perThreadLength;
  81. //循环创建多个下载线程
  82. do{
  83. if(endPosition>=contentLength)
  84. endPosition=contentLength-1;
  85. DownloadThreadthread=newDownloadThread(url,startPosition,endPosition,file);
  86. thread.addDownloadListener(listener);
  87. thread.start();
  88. threads.add(thread);
  89. startPosition=endPosition+1;//此处加1,从结束位置的下一个地方开始请求
  90. endPosition+=perThreadLength;
  91. }while(startPosition<contentLength);
  92. }

分段下载线程代码片段:

Java代码

  

爱华网本文地址 » http://www.aihuau.com/a/25101013/153041.html

更多阅读

怎样使用QQ旋风离线下载 精 qq旋风离线空间

qq旋风离线功能目前是仅仅面向qq会员的一个功能,这个主要是能够加快下载速度,尤其是对于一些比较稀缺和冷门的资源,今天就和大家分享下qq旋风离线下载使用方法,希望对大家有帮助。怎样使用QQ旋风离线下载 精——什么情况下使用离线下

谁是中国历史上使用年号最多的皇帝 历史上杀人最多的皇帝

感谢“草根名博”的重点推荐!谁是中国历史上使用年号最多的皇帝作者/乐奀  年号,是中国封建制度一大“发明”,系古代皇帝用于纪年的专有名号,被认为是帝王正统标志。不同的皇帝需有不同的年号,一般不用另一个皇帝的年号,否则会被认

C#多线程异步访问winform中控件 winform 多线程操作ui

我们在做winform应用的时候,大部分情况下都会碰到使用多线程控制界面上控件信息的问题。然而我们并不能用传统方法来做这个问题,下面我将详细的介绍。首先来看传统方法:public partial class Form1 : Form {public Form1(){Initialize

C#教程:线程的暂停与恢复

内容导读: 线程通过调用Suspend方法来暂停线程。当线程针对自身调用Suspend 方法时,调用将会阻止,直到另一个线程继续该线程。当一个线程针对另一个线程调用.Suspend 方法时,调用是非组阻止调线程的暂停与恢复线程通过调用Suspend方法来

在多线程中体会堆和栈的区别 多线程中栈与堆

最初涉及多线程程序涉及的时候经常会出现一些令人难以思议的事情,用堆和栈分配一个变量可能在以后的执行中产生意想不到的结果,而这个结果的表现就是内存的非法被访问,导致内存的内容被更改。理解这个现象的两个基本概念是:在一个进程

声明:《使用ApacheHttpClient实现多线程下载的小例子 thrift client 多线程》为网友不争炎凉分享!如侵犯到您的合法权益请联系我们删除