`
liangguanhui
  • 浏览: 112957 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

【原创】Java多线程断点下载理论

阅读更多

希望你转载文章的时候,麻烦保留作者信息。(夏威夷雪人 or 书虫)

1、断点下载的基本原理
  
  其实这个是HTTP协议的一部分。在HTTP 1.1,支持断点下载,断点HTTP请求跟一般的HTTP请求基本相同,只有两点不同:
  
(1)发起请求是HTTP的版本必须是HTTP/1.1
(2)在Header有这样一个节点:Range,格式是Range: bytes=起始字节-结束字节
  
  如果HTTP返回的状态码是206,则代表对方支持断点下载,否则就是不支持。另外我用HttpURLConnection的时候,找不到设置HTTP版本的方法,虽然在下载的时候很多网站照样支持,但感觉不是很踏实。希望可以找到解决的方法。(当然可以自己用Socket实现一个Http协议,不过重复轮子的事情貌似不好,也不怎么想用HttpClient这个大块头)
  
2、任务的分配算法
  
  如果我们认真看一下FlashGet的下载栏目,一定可以看到它有一堆表示进度的格子,这里,每个格子就代表固定长度的字节,从这里我们可以清晰地看到下载的进度以及每一部分下载的情况。我们这里也使用类似的方法,把整个文件按照固定的长度(4K)分成很多“格”,然后进行多线程下载。这里就产生一个问题:怎么决定每个格子哪个线程去下载?我们知道,下载的时候,发起连接现对来说是一个比较耗时的操作,所以,我们需要把任务尽可能平均分配,较少连接的次数。
  
  我们根据每一个未下载的格子的“相连”情况,分成若干“条”“任务链”。这里的“相连”,是指按顺序的每一个未下载的格子都是相连的,没有跳跃。任务刚开始的时候,只有一条“任务链”,但当开始之后,当某些部分格子下载完毕之后,就被分割成不止一条“任务链”了。同时因为可能每一个线程的下载速度各不相同,所以,每一条任务链的长度可能都不相同。这就产生一个问题,当某个线程先一步完成了,我们当然是让这个线程继续下载,这时,我们就需要重新分配“任务链”。(如果我们用FlashGet下载一个文件,观察它的“格子”,对这个“任务链”的概念应该会更加清楚)
  
  整个分配算法,抽象出来,其实就是:有m条绳子,需要对这些绳子合共剪n刀,如何剪法才能使剪出来的绳子的最长跟最短的差距最小?
  
  首先我们需要明确的是,无论是何种剪法,都需要遵守这个原则:对每条绳子的剪都必须是平均剪。至于原因,读者可以自己思考。
  
  开始的时候,我是打算枚举所有剪法,然后计算每一种的剪法中,最短跟最长的差距。不过发现算法不容易写(粗略想了一下,貌似是排列组合的问题),而且时间复杂度貌似有O(n的平方)这么多。
  
  后来才发现自己原来是绕了个大弯。剪法其实很简单,首先在这m条绳子里找到最长的一条,放下一个剪刀,这是第一轮;然后在这m条绳子里再找到最长的一条,找的时候,如果遇到放有剪刀的绳子,按照剪刀的数目重新计算平均的绳子长度,例如加入绳子有6,放有2把剪刀,我们就算他为6÷(2+1)=2,然后,又在最长的那里放下一个剪刀;……这样一直循环,直到放完所有剪刀。算法非常简单,而且时间复杂度只有O(n)。
  
3、缓冲写的功能
  
  一般的下载工具都有缓冲写的功能,这个功能貌似对硬盘保养有一定的帮助。由于我们的下载是多线程下载,一般的方法是每个线程每次下完一个格子之后然后把这个格子的数据放到一个List里面,然后检查这个List里面的数据时候超过一个额度,如果超过,就把这些数据写道文件里面。这里有两个问题:
  
(1)当这个线程写文件的时候,这个List我们当然要上锁的,这个时候,其余线程就不能往这个List里面放数据,被阻塞了。(解决方法很简单,把这个List的数据搬到另外一个B List里面,然后清空List的数据,再在这个线程根据B List慢慢写文件,这样其余线程就不会阻塞了)
  
(2)这种方法需要浪费一个本来是下载的线程来写文件。
  
  第二个问题解决的方法是另起一个线程来专门写文件。每次每个线程下载完一个格子之后,把这个格子的数据放到一个地方(可以是List,也可以是其它),然后通知那个专门写文件的线程。那个线程检查数据的数量,如果超过一个额度就写文件。
  
  很明显,这是一个典型的生产/消费模型。Java5已经帮我们准备好了一个接口——BlockingQueue,就不需要再重复造轮子了。
  
  最后差点忘了说,这里写文件由于需要跳跃写,所以需要使用RandomAccessFile,同时建议一开始就分配空间,减少产生文件碎片的可能。
  
4、使用NIO代替多线程+BIO
  
  貌似现在越来越流行NIO了,连Tomcat6都是NIO,我们也把我们的下载工具改造成NIO。具体的NIO原理就不在这里细说了,读者可以上网查查,不过由于HttpURLConnection和HttpClient都是基于BIO的,所以很遗憾,如果你要用NIO,你不得不自己实现Http的协议,虽然不是很难。

分享到:
评论

相关推荐

    Java多线程断点下载Sample

    在这个“Java多线程断点下载Sample”示例中,我们将深入探讨如何利用Java的多线程特性来实现文件的断点续传下载,并结合进度条展示下载进度。 首先,我们需要理解什么是多线程。在单线程环境中,程序的执行顺序是...

    Java 多线程断点下载文件

    Java多线程断点下载文件是一种高效的文件下载方式,它允许在下载过程中暂停并从上次停止的地方继续,尤其适用于大文件下载。以下是实现这一功能的关键知识点: 1. **获取文件信息**: - 使用`java.net.URL`和`java...

    java多线程断点下载

    Java多线程断点下载是网络编程中一个实用的技术,尤其在处理大文件时能显著提升用户体验。在本文中,我们将深入探讨这个主题,讲解如何使用Java实现多线程和断点续传功能。 首先,我们需要理解什么是多线程。在...

    java多线程断点续传下载

    Java多线程断点续传下载是一个复杂但实用的技术,尤其在处理大文件或网络不稳定时,能够提高用户体验并优化资源利用。以下是对这个主题的详细解析: **1. Java多线程** Java多线程是指在一个Java应用程序中同时执行...

    Java 多线程断点下载

    Java多线程断点下载是Java编程中一种高级技术,主要应用于大文件的网络传输,如视频、软件安装包等。这种技术结合了多线程和断点续传的概念,提高了下载效率并允许用户在中断后继续从上次停止的位置开始下载。 首先...

    java 多线程断点续传

    下面将详细探讨如何在Java中实现多线程断点续传。 首先,我们需要理解多线程的概念。在Java中,我们可以使用`Thread`类或`Runnable`接口来创建线程。当一个线程被创建后,它可以与主线程并行运行,每个线程都有自己...

    Java多线程断点下载

    ### Java多线程断点下载技术详解 在现代互联网应用中,大文件的高效下载是提升用户体验的关键之一。Java作为一种广泛使用的编程语言,在处理大文件下载时,采用多线程断点续传技术能显著提高下载速度和稳定性。本文...

    java 多线程断点下载

    Java多线程断点下载是实现大文件高效下载的一种技术,尤其在移动设备如Android上应用广泛。这种技术的关键在于利用多线程并发处理数据,提高下载速度,并且支持用户中断下载后,从上次停止的位置继续,避免了数据的...

    再分享一个Java 多线程断点式下载模块.rar

    多线程断点式下载示例代码,再分享一个Java 多线程断点式下载模块,主要原理是: 把context分为poolSize段,计算每段的长度。如果文件已存在,根据临时文件中记载的线程数量,继续上次的任务,如果下载的目标文件不...

    多线程断点下载

    通过以上讲解,我们可以看到多线程断点下载技术在Java和Android平台上的实现涉及了网络编程、多线程同步、文件操作等多个方面的知识,它在提升用户体验的同时,也对开发者的技术要求较高。在实际应用中,开发者需要...

    多线程断点下载(java线程学习)

    java中多线程下载学习,又新增了断点的实现,可以实现暂停继续下载网络文件的功能

    android多线程断点下载

    在Android开发中,多线程断点下载是一项重要的技术,特别是在处理大文件或者网络环境不稳定的情况下,能够提高下载效率并确保下载的连续性。本文将详细介绍如何在Android中实现多线程断点下载,以及如何封装一个易于...

    Android多线程断点下载(优化)

    在Android开发中,多线程断点下载是一种常见的优化策略,尤其在处理大文件时,如应用程序、视频或音频文件的下载。这种技术允许用户在任何时间暂停下载,并在稍后从停止的地方继续,而无需重新开始。在本文中,我们...

    Java实现多线程下载和断点续传

    1. 把每个下载文件切成若干个块...2. HTTP Header里增加Range,如果服务器返回Cotent-Range 说明服务器支持文件定位,可以实现多线程下载 详细看这里 http://blog.csdn.net/maoxiang/archive/2010/04/02/5446293.aspx

    java ftp 多线程 断点续传等知识

    而"多线程"和"断点"这两个文件名可能是指相关示例代码或文档,可以进一步帮助你理解和实践Java FTP的多线程下载和断点续传。 在实际应用中,还需要考虑其他因素,如错误处理、网络状况的监控、文件完整性检查等。...

    retrofit实现多线程断点下载,可暂停,开始

    在Android开发中,为了提供更好的用户体验,我们常常需要实现文件的多线程断点下载功能。这不仅可以提高下载速度,还能允许用户在任何时候暂停或继续下载。本篇将重点讲解如何利用Retrofit库和GreenDao数据库来实现...

    java断点续传,刚刚整理出来多线程处理

    在Java中,`Thread`类和`Runnable`接口是实现多线程的基础,我们可以创建多个线程实例,分别绑定到不同的下载任务上。 然而,实现多线程断点续传需要解决几个问题: 1. **同步管理**:多个线程可能会同时访问同一个...

    htp多线程断点下载文件

    在IT领域,网络数据传输是不可或缺的一部分,而断点续传和多线程下载技术则大大提升了文件下载的效率和用户体验。"htp多线程断点下载文件"这一主题,涉及了网络编程、多线程技术和文件处理等多个知识点。 首先,...

    java实现多线程断点续传下载

    在Java编程中,多线程和断点续传下载是两个关键的概念,它们在实际的网络应用开发中具有广泛的应用。本文将详细讲解这两个技术及其在Java中的实现。 首先,让我们了解一下多线程。在计算机科学中,多线程是指在一个...

Global site tag (gtag.js) - Google Analytics