在安卓的开发过程中,不应该放置过多的任务在主线程上,否则会导致页面加载变慢,用户的体验变差。因此,可以放在线程中执行的事务应该尽量放置在线程中。
下面,介绍使用线程,以及线程池的四种常见用法。均采用kotlin实现。
- 线程基本使用
//第一种
object:Thread(){
override fun run() {
println("测试")
}
}.start()
//第二种
Thread({
println("测试1")
}).start()
//三
thread(start = true){
println("测试2")
}
- 线程池
线程池的作用不多说了。直接介绍它的机制,如下:
类似设计模式中的责任链模式,应对的顺序如下:
- 如果线程中的核心线程没有达到上限,就由核心线程来进行任务的处理。
- 如果线程数大于或者等于核心线程的数量上限,就将任务加入任务队列,线程池中的线程在执行完自己的线程之后,会从任务队列之中不断取出任务进行处理。
- 如果连任务队列都满了,但是线程的总数据没有达到线程池设置的总的上限,就会创建非核心线程处理任务。(创建相对核心线程比较费时)
- 如果,超过了总线程的上限,就会执行饱和策略。
饱和策略(四种):
- CallerRunsPolicy:用调用者所在的线程来处理任务。此策略提供简单的反馈控制机制,能够缓解新任务的提交速度。
- DisCardPolicy:不能执行的任务,并将该任务删除。
- DiscardOldestPolicy:丢弃队列最近的任务,并执行当前的任务。
- AbordPolicy:表示无法处理新任务,并抛出RejectedExecutionException异常。(默认策略)
构造方法
public ThreadPoolExecutor(val corePoolSize:Int, //核心线程数
val maximumPoolSize:Int, //线程池允许的最大线程数
val keepAliveTime:Long, //非核心线程闲置的超时时间,超时回收
val unit:TimeUnit, //上一个参数的单位,有天、分等等
val workQueue:BlockingQueue<Runnable>,//任务队列
val threadFactory:ThreadFactory,//线程工厂
val handler:RejectedExecutionHandler){//饱和策略
....
}
线程池的种类
- FixedThreadPool
它是可重用固定线程数的线程池。只有核心线程,没有非核心线程,keepAliveTime的事件设置为0,任务队列采用了无界阻塞队列LinkedBlockingQueue。
构造方法:
val pool = ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS, LinkedBlockingDeque())
- CachedThreadPool
它是根据需要创建线程的线程池。无核心线程,非核心线程无界,使用阻塞队列SynchronousQueue,一个元素的插入必须等待另一个元素的移除。
构造方法:
val pool = ThreadPoolExecutor(0, Int.MAX_VALUE, 60L, TimeUnit.SECONDS, SynchronousQueue())
- SingleThreadExecutor
单工作线程,队列和第一个一样,
构造方法:
val pool = ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, LinkedBlockingDeque())
- ScheduledThreadPool
实现定时和周期性任务的线程池。任务队列无界,下面的3是核心线程数。
构造方法:
val pool = ScheduledThreadPoolExecutor(3)