赞
踩
既然Android中已经有了线程的概念,那么为什么需要使用线程池呢?我们从两个方面给出使用线程池的原因。
首先线程的新建和销毁都是存在性能上的消耗的,如果一个时间段有大量的网络请求,那么就需要多个线程的创建与销毁,性能上的损耗可想而知。
其次多个线程的存在也会占用CPU的执行时间段。我们知道如果只有一个CPU存在,那么线程的执行都是CPU轮流将执行时间分配给每一个线程。如果同时有多个子线程存在,那么相应的分配到主线程的CPU执行时间也会变少,这样App很大可能会出现卡顿现象。
鉴于上述两方面的原因,我们引进来了线程池这样一个概念,线程的创建、调度、销毁等都是由线程池来管理,这样就可以做到线程的重用,不必每次都新建一个线程,减少了线程创建和销毁的性能损耗。同时线程池会限制创建线程的个数,让App中的线程个数保持在一个可控的范围,这样也可以控制多个线程抢占主线程的资源。
1.重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。
2.能有效控制线程池的最大并发数,避免大量的线程之间因互相抢占系统资源而导致的阻塞现象。
3.能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。
Android中的线程池的概念来源于java中的Executor, Executor是一个接口,真正的线程池的实现为ThreadPoolExecutor. ThreadPoolExecutor提供了一系列参数来配置线程池,通过不同的参数可以创建不同类型的线程池.
ThreadPoolExecutor是线程池的真正实现,它的构造方法提供一系列参数来配置线程池.
我们来看看它的构造方法
源码路径: libcore/ojluni/src/main/java/java/util/concurrent/ThreadPoolExecutor.java
- // Public constructors and methods
-
- /**
- * Creates a new {@code ThreadPoolExecutor} with the given initial
- * parameters and default thread factory and rejected execution handler.
- * It may be more convenient to use one of the {@link Executors} factory
- * methods instead of this general purpose constructor.
- *
- * @param corePoolSize the number of threads to keep in the pool, even
- * if they are idle, unless {@code allowCoreThreadTimeOut} is set
- * @param maximumPoolSize the maximum number of threads to allow in the
- * pool
- * @param keepAliveTime when the number of threads is greater than
- * the core, this is the maximum time that excess idle threads
- * will wait for new tasks before terminating.
- * @param unit the time unit for the {@code keepAliveTime} argument
- * @param workQueue the queue to use for holding tasks before they are
- * executed. This queue will hold only the {@code Runnable}
- * tasks submitted by the {@code execute} method.
- * @throws IllegalArgumentException if one of the following holds:<br>
- * {@code corePoolSize < 0}<br>
- * {@code keepAliveTime < 0}<br>
- * {@code maximumPoolSize <= 0}<br>
- * {@code maximumPoolSize < corePoolSize}
- * @throws NullPointerException if {@code workQueue} is null
- */
- public ThreadPoolExecutor(int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue<Runnable> workQueue) {
- this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
- Executors.defaultThreadFactory(), defaultHandler);
- }

对应的参数说明:
定义的源码路径为: /libcore/ojluni/src/main/java/java/util/concurrent/Executors.java
根据参数的不同配置,Java内置了4种常用线程池:
特点和对比图
总结的思维导图:
- // 1. 创建线程池
- // 创建时,通过配置线程池的参数,从而实现自己所需的线程池
- Executor threadPool = new ThreadPoolExecutor(
- CORE_POOL_SIZE,
- MAXIMUM_POOL_SIZE,
- KEEP_ALIVE,
- TimeUnit.SECONDS,
- sPoolWorkQueue,
- sThreadFactory
- );
- // 注:在Java中,已内置4种常见线程池
-
- // 2. 向线程池提交任务:execute()
- // 说明:传入 Runnable对象
- threadPool.execute(new Runnable() {
- @Override
- public void run() {
- ... // 线程执行任务
- }
- });
-
- // 3. 关闭线程池shutdown()
- threadPool.shutdown();
-
- // 关闭线程的原理
- // a. 遍历线程池中的所有工作线程
- // b. 逐个调用线程的interrupt()中断线程(注:无法响应中断的任务可能永远无法终止)
-
- // 也可调用shutdownNow()关闭线程:threadPool.shutdownNow()
- // 二者区别:
- // shutdown:设置 线程池的状态 为 SHUTDOWN,然后中断所有没有正在执行任务的线程
- // shutdownNow:设置 线程池的状态 为 STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表
- // 使用建议:一般调用shutdown()关闭线程池;若任务不一定要执行完,则调用shutdownNow()

我们通过源码来看下是怎么使用的:
源码片段:
/Dialer/java/com/android/voicemail/impl/transcribe/TranscriptionService.java
1. 创建一个单例线程池
- private ExecutorService getExecutorService() {
- if (executorService == null) {
- // The common use case is transcribing a single voicemail so just use a single thread executor
- // The reason we're not using DialerExecutor here is because the transcription task can be
- // very long running (ie. multiple minutes).
- executorService = Executors.newSingleThreadExecutor();
- }
- return executorService;
- }
2. 调用 execute(Runnable runnable)方法,执行任务
- activeTask =
- configProvider.shouldUseSyncApi()
- ? new TranscriptionTaskSync(
- this, new Callback(), workItem, getClientFactory(), configProvider)
- : new TranscriptionTaskAsync(
- this, new Callback(), workItem, getClientFactory(), configProvider);
- //执行任务
- getExecutorService().execute(activeTask);
3. 任务执行完毕后,调用shutdown方法
- @Override
- @MainThread
- public void onDestroy() {
- if (executorService != null) {
- executorService.shutdownNow();
- executorService = null;
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。