IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android进阶——线程治理与线程池 -> 正文阅读

[移动开发]Android进阶——线程治理与线程池

1. 为什么需要线程池

程序中不管是网络请求、文件IO、数据库操作等其他耗时操作都需要异步进行,而由于线程创建和销毁都需要一定的开销,如果每次执行异步任务都重新创建一个线程,并在完成任务后直接进行销毁,这会消耗大量资源。JAVA在1.5中提供了Executor,通过将任务的创建和执行解耦, 如下图所示
在这里插入图片描述
即通过Runnable和Callable接口实现延时启动/异步启动任务并通过Future返回执行结果
整个Executor最核心的就是ThreadPoolExecutor,我们首先来看看他的原理;

2. ThreadPoolExecutor

2.1 ThreadPoolExecutor的构造

ThreadPoolExecutor一共有四个构造方法,如下所示:

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }
    
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        ...
    }

可以看到最终都是调用了最后一个构造,其参数含义如下:

corePoolSize :核心线程数,默认情况下新建的线程池是空的,当有新任务进来时,会判断当前线程数量是否小于核心线程数,小于则创建新线程执行该任务,反之不会创建,另外如果在创建线程池的同时调用了prestartAllcoreThread()则会在初始化完成后新建全部核心线程并等待任务;
maximumPoolSize : 最大线程数,一个新任务进来时,如果当前任务队列已满但线程数还没有达到最大线程数,则创建新线程;
keepAliveTime : 非核心线程闲置的超时回收时间,默认是1000ms,当非核心线程闲置超过这个时间后将会被回收,在一些任务数量多、任务平均耗时短的业务场景下可以适当调大此值以提高线程池效率,如果设置了allowCoreThreadTimeout(true)的话,则此超时时间限制也会用于核心线程;
unit: keepAliveTime参数的单位,可以是天、时、分、秒、毫秒;
workQueue: 任务队列,是一个阻塞队列;
threadFactory: 线程工厂,可以用它来为线程池中的线程设置名称,用的场景不多,一般默认不传该参数即可;
handler: 饱和策略,当线程池中任务队列已满且当前线程数已达到最大线程,如果此时有新任务进入,会触发饱和策略,默认为AbortPolicy,表示无法处理新任务,并抛出RejectedExecutionException异常。此外还有3种策略,它们分别如下:
①CallerRunsPolicy: 用调用者所在的线程来处理任务。此策略提供简单的反馈控制机制,能够减缓新任务的提交速度。
②DiscardPolicy: 不能执行的任务,并将该任务删除。
③DiscardOldestPolicy: 丢弃队列最近的任务,并执行当前的任务。

2.2 ThreadPoolExecutor中新任务处理流程

① 当一个新任务进入时,首先会判断当前线程数是否达到核心线程数,如果没达到则创建一个新的核心线程执行该任务;
② 如果当前未达到核心线程数,则创建核心线程执行任务,如已达到核心线程数,则检查当前任务队列是否已满;
③ 如果当前任务队列未满,则将新任务加到任务队列中,如任务队列已满,则判断当前线程数是否达到最大线程数;
④ 如果已经达到最大线程数,则触发饱和机制,如果未达到最大线程数,则创建一个新的线程执行新任务;

在这里插入图片描述

4.3 常用线程池

4.3.1 FixedThreadPool
// 构造方法
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }

通过构造方法可以很容易看出,FixedThreadPool特点:①核心线程数 = 最大线程数 = nThreads(构造传入);②keepAliveTime为0;③任务队列类型为一个无界阻塞队列
结合前面对于ThreadPoolExecutor构造参数的解释,可以得出FixedThreadPool处理任务的过程如下:
①如果当前运行的线程数少于corePoolSize, 会立刻创建新线程执行任务。
②当线程数到达corePoolSize后,将任务加入到LinkedBlockingQueue中。
③当线程执行完任务后,会循环从LinkedBlockingQueue中获取任务来执行。

FixedThreadPool使用了LinkedBlockingQueue, 也就是无界队列(队列最大可容纳Integer.MAX_VALUE), 因此理论上任务可以无限添加,直到内存溢出;

4.3.2
  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2022-03-03 16:26:11  更:2022-03-03 16:26:16 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 17:09:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码