多线程断点续传(二)
2016-07-20 16:59
302 查看
一、 学习内容
1、 多文件下载列表的显示2、 启动多个线程分段下载
二、 多线程下载原理简介
假设要分3个线程下载一个100字节的文件:从头到尾,每个线程下载一段三、 学习点
1、 Adapter的getCount()
2、 Adapter的ViewHolder
3、 Adapter的notifyDataSetChanged()
getView() 方法会重新调用一遍4、 单例模式
1) 【问题】:多个线程在操作同一个数据库,导致数据库锁定的问题数据库设置为单例模式,保证这个类只有一个对象,一个实例。多个实例会产生多个地方去操作数据库。单例的话,也就是说只有一个实例会对数据库进行访问操作。
2) 【单例设计】:永远只会被实例化一次
a) 私有化构造方法 |
b) 定义静态对象引用 |
c) 获得类实例的静态方法 |
5、 Java中线程池
自己创建和销毁线程也是会销毁性能的,减少线程创建和销毁所使用的时间,让程序运行速度更快。线程组成的池塘,当线程运行完成之后,不会简单的销毁线程,而是出于等待,当有新的任务开始,就从线程池中拿出线程复用,这样就减少了线程创建和销毁的次数,提高了程序运行的性能。
1) 线程池接口:ExecutorService
提供对线程池中的线程进行集中的管理,比如在某一段时间内,启动某些任务,可以对所有的线程进行停止,启动的任务。减少线程创建和销毁所使用的时间,便于服务器进行管理。减少了服务器频繁创建线程的资源消耗。
2) Executors类提供四种线程池:
a) newCachedThreadPool():带缓存的线程池 线程池中的线程个数对于任务所需要的线程个数,就会将空闲的线程回收 一旦线程中的线程不足任务所需的线程,就会将回收的线程重新拿取出来进行使用 线程数量大小没有进行限制,与能够系统支持的线程数量有关 |
b) newFixedThreadPool(int):固定线程数量的线程池 |
c) newScheduledThreadPool():可以周期性的,定时的去执行任务,线程数量没有做限制 |
d) newSingleThreadExecutor():单个线程的线程池,所有的任务排队执行,先来先执行 |
四、 案例小结
1、 多线程(分段下载、线程池)
1) 分段下载:一个文件分成了的多段进行下载,每一个线程下载文件中的某个范围a) 下载之前需要先计算出每个线程需要下载的长度,根据文件的长度/开启线程的个数 |
b) 开启线程下载,通过Range 设置开始下载点和结束下载点,来获取每个线程要下载的数据范围 conn.setRequestProperty(“Range”, “bytes=” + start + “-” + end); |
线程池采用的是newCachedThreadPool带缓存的线程池,excute执行线程。好处是,减少了线程创建和销毁所需要的时间,线程池会直接将空闲的线程拿过来进行使用。
2、 续传(单例模式、线程安全)
把线程下载的进度保存起来,保存到数据库中。多线程对数据库的访问可能会造成数据库的表或者数据库的锁定。
1) 单例模式:
通过数据库的帮助类DBHelper来操作数据库,如果有多个实例的话,就会在多个地方操作数据库,这是不安全的,所以将DBHelper设计为单例模式。
a) 将构造方法私有化 |
b) 初始化静态对象引用 |
c) 创建静态公共方法getIntance,保证该数据库帮助类DBHelper只创建一次 先判断静态对象是否为空 如果为空,创建该数据库帮助类DBHelper 返回该数据库帮助类DBHelper |
a) 将数据库的增删改都设置为synchronized同步方法,保证同一时间段只有一个线程在操作修改数据库内容 |
b) 查询数据库不需要设置synchronized同步方法,因为并没有对数据库进行操作。使用同步方法会销毁程序运行的性能,所以查询建议不用使用同步锁。 |
c) 修改获取查询数据库的方式: 获取可读数据库:(查询) SQLiteDatabase database = dbHelper.getReadableDatabase(); 获取可写数据库:(增删改) SQLiteDatabase database = dbHelper.getWritableDatabase(); |
3、 下载(网络连接、文件操作)
1) 网络连接:通过HttpURLConnection设置和获取网络请求2) 文件操作:关键使用RandomAccessFile文件操作流,可以在文件的任意位置开始写入,通过使用seek(index)设置文件写入的指针位置
五、 问题反馈记录
1、 ListView的convertView 复用问题
1) 【问题】当一个屏幕不能显示全部的item的时候,就会因为item的复用而出现错乱2) 【原因】设置文件名和按钮的操作放在第一次实例化的括号里是不可取的。
2、 ListView的item问题
生成list的 mFileList的时候 注意添加的fileinfo的 id要和position一致,不然会错乱(这点不太好 比如加入删除任务功能后会比较麻烦)3、 下载,停止按钮注意不能多次点击需要可以在代码中进行限制
4、 退出Activity时,线程仍然会下载一段时间且不会保存
可以在service的onDestory() 方法中对map mtasks遍历 改isPaused为true5、 删除未完成下载文件后,数据库中未删除,会导致下载不完整
可以在service中初始化时判断文件是否存在6、 ftruncate failed:ENOSPC(No space left on device)
1) 【报错地方】accessFile.setLength(length);2) 【原因】是需要下载的内容超过了Android设备的可存储空间。
7、 下载内容过大,设置Progress出现问题
1) 【问题】设置进度的时候,由于下载内容过大,mFinished * 100 会导致丢失精度2) 【解决】intent.putExtra(“finished”, (int) (mFinished * 1.0 / mFileInfo.getLength() * 100)); 并且可以使用long类型
【Demo】:
CSDN:http://download.csdn.net/detail/yecjl/9581465
相关文章推荐
- Python3写爬虫(四)多线程实现数据爬取
- C#实现多线程的同步方法实例分析
- C#线程间不能调用剪切板的解决方法
- 浅谈chuck-lua中的多线程
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#文件断点续传实现方法
- C#多线程编程中的锁系统(三)
- C#线程同步的三类情景分析
- C#获取进程或线程相关信息的方法
- 简单对比C#程序中的单线程与多线程设计
- C#停止线程的方法
- 解析C#多线程编程中异步多线程的实现及线程池的使用
- C#子线程更新UI控件的方法实例总结
- C#多线程学习之(六)互斥对象用法实例
- C#线程队列用法实例分析
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析