[TOC]

线程池原理

优点:

  • 能够实现复用
  • 线程统一管理

核心参数

  • corePoolSize 为线程池的基本大小。
  • maximumPoolSize 为线程池最大线程大小。
  • keepAliveTimeunit 则是线程空闲后的存活时间。
  • workQueue 用于存放任务的阻塞队列。
  • handler 当队列和最大线程池都满了之后的饱和策略。

执行流程

提交任务》核心线程是否已满》阻塞队里是否已满》线程池是否已满》拒绝策略

拒绝策略

AbortPolicy: 直接拒绝所提交的任务,并抛出RejectedExecutionException异常。

CallerRunsPolicy:只用调用者所在的线程来执行任务。

DiscardPolicy:不处理直接丢弃掉任务。

DiscardOldestPolicy:丢弃掉阻塞队列中存放时间最久的任务,执行当前任务。

延时任务与定时任务

线程池可以处理延时任务,设置延迟时间执行任务

通过execute执行无返回值,而submit提交则有Future的返回值,其中get方法可以设置timeout时间,若deadline到达,还没有get到结果,则抛出异常。通过这个方法可以处理定时任务。但是值得注意的是,该方法会直接阻塞get所在线程!!若是在主线程中直接引起ui卡住,长时间超过5s则ANR。若想不卡主线程,而设置定时任务可以采用timer方式,除了这种方式外还可以采用开启守护线程方式来解决。

应用场景

当需要频繁创建线程来执行任务的时候

需要延迟执行任务

多线程&多任务场景以及单线程场景

其他场景

例如协程。协程(kotlin)的执行环境也是线程池的应用之一。当在主线程中使用协程提交任务,这些任务会被调度到线程池的各个线程中,虽然不在同一个线程,但是能够保证一定的执行顺序。通过自定义协程调度器可以设置其执行的指定线程池。总的来说,依靠的还是线程池。

例子

class SingleThreadExecutorDispatcher
: AbstractCoroutineContextElement(ContinuationInterceptor),
ContinuationInterceptor {

private val executorService = Executors.newSingleThreadExecutor {
Thread(it, "SingleThreadExecutor")
}

override fun <T> interceptContinuation(continuation: Continuation<T>): Continuation<T> {
return MyContinuation(continuation)
}

inner class MyContinuation<T>(private val origin: Continuation<T>) : Continuation<T> {
override val context: CoroutineContext = origin.context
override fun resumeWith(result: Result<T>) {
executorService.submit {
origin.resumeWith(result)
}
}
}

fun close() {
executorService.shutdown()
}
}

fun main() = runBlocking {
val dispatcher = SingleThreadExecutorDispatcher()
log("AA")
val job = GlobalScope.launch(dispatcher) {
delay(100)
log("BB")
}
job.join()
dispatcher.close()
}

输出:

[main] AA
[SingleThreadExecutor] BB

Process finished with exit code 0