原帖地址 http://automaticthoughts.iteye.com/blog/1612388
1.使用线程池的目的:
1.1减少使用与创建线程池的次数,每个线程都可以重复利用,可执行多个任务。
1.2可以更具当前手机系统的内存大小,来动态调整线程池里面固定的线程数量,造成阻塞,排队,不会在线程上浪费过多的内存
同时使用线程的时候,我们用的是用来请求服务器,造成服务器过大的负担
2.线程池的使用
在Java JDK1.5之后关于线程池的使用有了很大的改善,在Java.util.concurrent包中介绍了对于线程池的使用,XMPP协议的使用着,
Asmack有3个关于线程池的使用的地方,一个是关于发送心跳包来维系与服务器的长链接的地方,一个是接收消息的阻塞线程队列,一个是发送
Message 字节流的地方,
Java中线程池的最顶部的接口是Executor,严格来将Executor并不是一个线程池,而是一个执行线程的工具,真正的线程池接口是
ExecutorService
Executor中几个比较重要的类相关介绍:
ExecutorService,ScheduleExecutorService,ThreadPoolExecutor,ScheduledThreadPoolExecutor:
ExecutorService:就是一个真正的线程池的接口
ScheduleExecutorService:与Timer相似,用来解决需要重复执行的任务线程管理
ThreadPoolExecutor:ExecutorService的默认实现类
ScheduledThreadPoolExecutor:周期性重复调用的线程池管理,例如Android中的循环切换切换广告栏图片,这个任务就是循环重复的
,在执行完一次之后,需要重复循环调用Schedule本身就是目录或者时刻表的意思
Executor类里面提供了一些静态的工厂类,用来创建不同需求的线程池
2.1 newSingleThreadExecutor: 创建一个只存在单个线程的线程池,也就是单个线程执行所有的任务,如果唯一的那一条线程出现异
常Interruput,那么会有一个新的线程来代替之前的线程,此线程池保证所有的任务按照任务的提交顺序执行
2.2 newFixedThreadPool:创建固定大小的线程池,每次提交一个任务就在线程池中添加一条,知道线程池中的数量达到创建是设置的
数目,线程池的大小一旦达到最大值就没办法改变,除非线程池中的某条线程出现异常,才会创建一个备胎,备胎就可以转正了,
2.3 newCacheThreadPool:创建一个可以缓存的线程池,当需要处理的任务添加的时候能够智能的添加新线程来处理任务,那么就会回
收部分不执行的线程,或者处于休闲状态的线程池(60秒的时间内,啥都没干的线程),线程池的大小完全依赖于JVM
2.4 newScheduledThreaPool:创建一个没有大小限制的线程池,此线程中池用来周期性重复的执行某条线程
3 关于ThreadPoolExecutor
ThreadPoolExecutor的完整构造与签名是:ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit)
构造函数中的参数意义:corePoolSize 线程池中保存的线程数量,包括空闲线程
maximumPoolSize 线程池中保存线程的最大值
keepAliveTime 当线程池中的线程数量大于corePoolSize ,终止多余的空闲线程,等待新任务的最长时间,其实表示的是多长时间把
线程分类为空闲线程
unit 构造函数中keepAliveTime的时间单位
4 queue的三种类型
排队通常有三种通用的策略:
4.1直接提交
工作队列的默认选项是 SynchronousQueue,它将任务直接提交给线程而不保持它们。在此,如果不存在可用于立即运行任
务的线程,则试图把任务加入队列将失败,因此会构造一个新的线程。此策略可以避免在处理可能具有内部依赖性的请求集时出现锁。直接提
交通常要求无界 maximumPoolSizes 以避免拒绝新提交的任务。当命令以超过队列所能处理的平均数连续到达时,此策略允许无界线程具有增
长的可能性。
4.2无界队列
使用无界队列(例如,不具有预定义容量的 LinkedBlockingQueue)将导致在所有 corePoolSize 线程都忙时新任务在队列
中等待。这样,创建的线程就不会超过 corePoolSize。(因此,maximumPoolSize 的值也就无效了。)当每个任务完全独立于其他任务,即
任务执行互不影响时,适合于使用无界队列;例如,在 Web 页服务器中。这种排队可用于处理瞬态突发请求,当命令以超过队列所能处理的
平均数连续到达时,此策略允许无界线程具有增长的可能性。
4.3有界队列
当使用有限的 maximumPoolSizes 时,有界队列(如 ArrayBlockingQueue)有助于防止资源耗尽,但是可能较难调整和控
制。队列大小和最大池大小可能需要相互折衷:使用大型队列和小型池可以最大限度地降低 CPU 使用率、操作系统资源和上下文切换开销,
但是可能导致人工降低吞吐量。如果任务频繁阻塞(例如,如果它们是 I/O 边界),则系统可能为超过您许可的更多线程安排时间。使用小
型队列通常要求较大的池大小,CPU 使用率较高,但是可能遇到不可接受的调度开销,这样也会降低吞吐量。
5 BlockingQueue的选择
5.1使用直接提交策略,也即SynchronousQueue。在某次添加元素后必须等待其他线程取走后才能继续添加。
5.2使用无界队列策略,即LinkedBlockingQueue 这个就拿newFixedThreadPool来说,根据前文提到的规则:
如果运行的线程少于 corePoolSize,则 Executor 始终首选添加新的线程,而不进行排队。那么当任务继续增加,会发生什么呢?
5.3有界队列,使用ArrayBlockingQueue。