前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Android 异步操作】线程池 ( 线程池简介 | 线程池初始化方法 | 线程池种类 | AsyncTask 使用线程池示例 )

【Android 异步操作】线程池 ( 线程池简介 | 线程池初始化方法 | 线程池种类 | AsyncTask 使用线程池示例 )

作者头像
韩曙亮
发布2023-03-28 18:44:08
3K0
发布2023-03-28 18:44:08
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

一、线程池简介


线程池一般是实现了 ExecutorService 接口的类 , 一般使用 ThreadPoolExecutor 线程池 ;

线程池优势 :

减少线程对象个数 : 避免每次执行子线程任务时 , 都要执行 new Thread() 构造函数 , 避免每次创建一个新的对象 , 减少开销 ;

线程管理 : 方面对线程进行管理 , 已存在的线程直接重用 , 这样减少了线程对象创建的个数 , 降低了 CPU 资源开销 ;

控制并发数 : 每个 CPU 都有最合适的并发线程数 , 如果并发数过高 , 就会导致资源竞争 , 线程堵塞 , 合理控制并发数 , 能提高 CPU 使用效率 ;

二、线程池初始化方法简介


线程池初始化方法简介 :

newCachedThreadPool : 创建 可缓存线程池 ; 如果线程池长度超过处理需要 , 则回收线程 , 如果不能回收 , 就创建新线程 ;

newFixedThreadPool : 创建 定长线程池 ; 可以设置线程最大并发数 , 如果并发数已满 , 后续任务会在任务队列中等待 ;

newScheduledThreadPool : 创建 定长周期任务线程池 ; 该线程池支持周期性任务执行 ;

newSingleThreadExecutor : 创建 单线程化线程池 ; 该线程只有一个工作线程 , 可以保证所有任务按照指定的顺序执行 ; 如 FIFO 先进先出顺序 , 或 LIFO 后进先出顺序 ;

三、线程池使用示例


以 AsyncTask 源代码为例 , 在 SerialExecutor 中 , 最终使用的是 THREAD_POOL_EXECUTOR.execute(mActive) 执行线程任务 ; 线程池通过 execute 函数执行外部任务 ;

THREAD_POOL_EXECUTOR 是 自己配置的线程池 , 没有使用 Java 默认提供的四种线程池 , Java 提供的四种线程池是 可缓存线程池 , 定长线程池 , 定长周期任务线程池 , 单线程线程池 ;

THREAD_POOL_EXECUTOR 线程池配置代码如下 :

代码语言:javascript
复制
new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
            TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory,
            new ThreadPoolExecutor.DiscardOldestPolicy());

下面对 THREAD_POOL_EXECUTOR 自己配置的线程池参数进行说明解析 ,

CORE_POOL_SIZE 核心线程数 ,

MAXIMUM_POOL_SIZE 最大线程数 , 非核心线程就是二者相减 ,

KEEP_ALIVE 非核心线程闲置时间 , 超过一定时间非核心线程就会回收 ,

TimeUnit.SECONDS 非核心线程闲置时间单位 “秒” ,

sPoolWorkQueue 线程池任务队列 ,

sThreadFactory 线程工厂 , 作用是用于创建线程

线程池原理说明 :

线程池线程分类 : 线程池的线程分为 核心线程 , 非核心线程 两类 ;

非核心线程闲置时间 : 非核心线程 超过一定的闲置时间 , 就会被回收 ;

假设线程池最大线程数是

8

, 核心线程数

3

, 非核心线程数

5

;

线程池任务队列 : 当启动一个线程池后 , 线程池会不停地从该任务队列中取出任务执行 ,

  • 启动核心线程 : 如果当前核心线程没有满 , 小于
3

个 , 那么创建核心线程执行该任务 ,

  • 启动非核心线程 : 如果当前核心线程已经有
3

个 , 但是 非核心线程没有满 , 小于

5

个 , 那么会创建非核心线程 , 执行该任务 ;

执行者 Executor 执行任务处理 : 如果核心线程数 有

3

个 , 非核心线程数有

5

个 , 最大线程数已满 ; 如果用户再提交任务给线程池 , 就会 将任务放入线程池任务队列中排队 ; 如果此时任务队列也满了 , 此时就会 抛出异常 ; 开发者应该通过回调处理被拒绝的任务 ;

线程池从任务队列取出任务并执行 : 线程数量

C
  • 线程数量
C < 3

: 创建核心线程执行任务 ;

  • 线程数量
3 \leq C < 8

: 创建非核心线程执行任务 ;

用户调用 Executor 的 execute 执行任务 : 线程数量

C
  • 线程数
C = 8

, 任务队列没满 : 将任务放入任务队列 ;

  • 线程数
C = 8

, 任务队列已满 : 会报出异常 , 使用 Handler 处理错误 ;

代码语言:javascript
复制
    /**
     * 创建自定义线程池 , 用于并行执行任务 .
     */
    public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
            TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory,
            new ThreadPoolExecutor.DiscardOldestPolicy());

    /**
     * 一个 Executor 执行者 , 以串行顺序 , 一次执行一个任务 ; 针对特定进行 , 该序列化是全局的 , 
     * 即 一个进程只有一个该执行者 . 
     */
    public static final Executor SERIAL_EXECUTOR = Utils.hasHoneycomb() ? new SerialExecutor() :
            Executors.newSingleThreadExecutor(sThreadFactory);

    @TargetApi(11)
    private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
                THREAD_POOL_EXECUTOR.execute(mActive);
            }
        }
    }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-11-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、线程池简介
  • 二、线程池初始化方法简介
  • 三、线程池使用示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档