Android 多线程之线程池

简介:

Android 多线程系列

Android线程池的真正实现是ThreadPoolExecutor

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
}
  • corePoolSize:表示核心线程数。默认情况下核心线程会在线程池中一直存活,即使处于闲置状态。如果将ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true,那核心线程也会有超时策略,时间间隔由keepAliveTime指定
  • maximumPoolSize:线程池的最大线程数。当活动的线程数达到这个数值后,后续的新任务就会被阻塞
  • keepAliveTime:线程超时策略的超时时间,超过这个时间,非核心线程会被回收,核心线程要看allowCoreThreadTimeOut属性
  • unit:keepAliveTime的单位
  • workQueue:线程池的任务队列,如LinkedBlockingQueue,SynchronousQueue等
  • ThreadFactory:线程工厂,为线程池创建新线程。ThreadFactory是一个接口,只有一个newThread方法
执行过程
  • 如果线程池中的线程数未达到核心线程数,就创建核心线程执行新的任务
  • 如果线程池中的线程数已经达到核心线程数,就将任务插入到任务队列中
  • 如果无法将任务插入队列,说明队列已经满了,这个时候如果线程数未达到线程池的最大线程数,就创建非核心线程执行任务
  • 如果任务队列满了,线程数已经达到最大值,就拒绝执行任务。ThreadPoolExecutor会调用RejectedExecutionHandler的rejectedExecution方法通知调用者

常见的四种线程池

FixedThreadPool
  • 创建方法
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
}
  • 可以看到默认构造函数需要传入核心线程数,且核心线程数和线程总数相同,也就是只有核心线程,同时没有超时时间,任务队列为LinkedBlockingQueue
  • 由于只有核心线程,且没有超时策略,FixedThreadPool中的线程会一直存活,除非线程池被关闭。因此能快速响应外界的请求
  • 所有的核心线程都处于活动状态时,新的任务都会处于等待状态
CachedThreadPool
  • 创建方法
public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
}
  • CachedThreadPool只有非核心线程,且数量为Integer.MAX_VALUE,超时时间为60秒。
  • CachedThreadPool采用的任务队列为SynchronousQueue,因此只要有新的任务来就会立刻被执行。
  • 由于只有非核心线程,且有超时策略,当没有任务时,CachedThreadPool实际上一个线程也没有。
  • CachedThreadPool比较适合执行大量耗时较少的任务
SingleThreadExecutor
  • 创建方法
public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
}
  • SingleThreadExecutor只有一个核心线程,且没有超时策略,任务队列为LinkedBlockingQueue。
  • SingleThreadExecutor确保所有的任务都在同一个线程中按顺序执行,这样这些任务就不需要处理线程同步的问题
ScheduledThreadPool
  • 创建方法
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
        return new ScheduledThreadPoolExecutor(corePoolSize);
}

public ScheduledThreadPoolExecutor(int corePoolSize) {
        super(corePoolSize, Integer.MAX_VALUE,
              DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
              new DelayedWorkQueue());
}
  • ScheduledThreadPool的核心线程数是固定的,必须在创建时指定。非核心线程数是没有限制的。当非核心线程空闲时会被立即回收。
  • ScheduledThreadPool的任务队列为DelayedWorkQueue,因此可以用来执行一些定时任务和具有周期重复的任务

总结

  • 以上的四种常用的线程池虽然是系统默认提供的,但是我们在使用时还是要仔细选择。
  • 比如FixedThreadPool和SingleThreadExecutor中的任务队列为LinkedBlockingQueue,且没有指定队列的默认容量,而LinkedBlockingQueue的默认容量为Integer.MAX_VALUE,因此有可能造成队列任务过多而占用过多内存甚至发生OOM的情况
  • ScheduledThreadPool和CachedThreadPool的问题则是线程最大的数量为Integer.MAX_VALUE,可能导致创建大量的线程,引发OOM
  • 以上都是需要注意的地方。另外还是推荐用ThreadPoolExecutor根据实际需要手动创建线程池

            欢迎关注我的微信公众号,期待与你一起学习,一起交流,一起成长!

AntDream

目录
相关文章
|
30天前
|
监控 Kubernetes Java
阿里面试:5000qps访问一个500ms的接口,如何设计线程池的核心线程数、最大线程数? 需要多少台机器?
本文由40岁老架构师尼恩撰写,针对一线互联网企业的高频面试题“如何确定系统的最佳线程数”进行系统化梳理。文章详细介绍了线程池设计的三个核心步骤:理论预估、压测验证和监控调整,并结合实际案例(5000qps、500ms响应时间、4核8G机器)给出具体参数设置建议。此外,还提供了《尼恩Java面试宝典PDF》等资源,帮助读者提升技术能力,顺利通过大厂面试。关注【技术自由圈】公众号,回复“领电子书”获取更多学习资料。
|
4天前
|
Python
python3多线程中使用线程睡眠
本文详细介绍了Python3多线程编程中使用线程睡眠的基本方法和应用场景。通过 `time.sleep()`函数,可以使线程暂停执行一段指定的时间,从而控制线程的执行节奏。通过实际示例演示了如何在多线程中使用线程睡眠来实现计数器和下载器功能。希望本文能帮助您更好地理解和应用Python多线程编程,提高程序的并发能力和执行效率。
32 20
|
10天前
|
安全 Java C#
Unity多线程使用(线程池)
在C#中使用线程池需引用`System.Threading`。创建单个线程时,务必在Unity程序停止前关闭线程(如使用`Thread.Abort()`),否则可能导致崩溃。示例代码展示了如何创建和管理线程,确保在线程中执行任务并在主线程中处理结果。完整代码包括线程池队列、主线程检查及线程安全的操作队列管理,确保多线程操作的稳定性和安全性。
|
3月前
|
Prometheus 监控 Cloud Native
JAVA线程池监控以及动态调整线程池
【10月更文挑战第22天】在 Java 中,线程池的监控和动态调整是非常重要的,它可以帮助我们更好地管理系统资源,提高应用的性能和稳定性。
265 64
|
2月前
|
NoSQL Redis
单线程传奇Redis,为何引入多线程?
Redis 4.0 引入多线程支持,主要用于后台对象删除、处理阻塞命令和网络 I/O 等操作,以提高并发性和性能。尽管如此,Redis 仍保留单线程执行模型处理客户端请求,确保高效性和简单性。多线程仅用于优化后台任务,如异步删除过期对象和分担读写操作,从而提升整体性能。
79 1
|
3月前
|
监控 安全 Java
在 Java 中使用线程池监控以及动态调整线程池时需要注意什么?
【10月更文挑战第22天】在进行线程池的监控和动态调整时,要综合考虑多方面的因素,谨慎操作,以确保线程池能够高效、稳定地运行,满足业务的需求。
136 38
|
2月前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
3月前
|
API Android开发 iOS开发
深入探索Android与iOS的多线程编程差异
在移动应用开发领域,多线程编程是提高应用性能和响应性的关键。本文将对比分析Android和iOS两大平台在多线程处理上的不同实现机制,探讨它们各自的优势与局限性,并通过实例展示如何在这两个平台上进行有效的多线程编程。通过深入了解这些差异,开发者可以更好地选择适合自己项目需求的技术和策略,从而优化应用的性能和用户体验。
|
3月前
|
Java
.如何根据 CPU 核心数设计线程池线程数量
IO 密集型:核心数*2 计算密集型: 核心数+1 为什么加 1?即使当计算密集型的线程偶尔由于缺失故障或者其他原因而暂停时,这个额外的线程也能确保 CPU 的时钟周期不会被浪费。
158 4
|
3月前
|
Java
线程池内部机制:线程的保活与回收策略
【10月更文挑战第24天】 线程池是现代并发编程中管理线程资源的一种高效机制。它不仅能够复用线程,减少创建和销毁线程的开销,还能有效控制并发线程的数量,提高系统资源的利用率。本文将深入探讨线程池中线程的保活和回收机制,帮助你更好地理解和使用线程池。
164 2

热门文章

最新文章

  • 1
    如何修复 Android 和 Windows 不支持视频编解码器的问题?
  • 2
    【08】flutter完成屏幕适配-重建Android,增加GetX路由,屏幕适配,基础导航栏-多版本SDK以及gradle造成的关于fvm的使用(flutter version manage)-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 3
    当flutter react native 等混开框架-并且用vscode-idea等编译器无法打包apk,打包安卓不成功怎么办-直接用android studio如何打包安卓apk -重要-优雅草卓伊凡
  • 4
    【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
  • 5
    APP-国内主流安卓商店-应用市场-鸿蒙商店上架之必备前提·全国公安安全信息评估报告如何申请-需要安全评估报告的资料是哪些-优雅草卓伊凡全程操作
  • 6
    【09】flutter首页进行了完善-采用android studio 进行真机调试开发-增加了直播间列表和短视频人物列表-增加了用户中心-卓伊凡换人优雅草Alex-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草Alex
  • 7
    Android经典面试题之Kotlin中Lambda表达式和匿名函数的区别
  • 8
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 9
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 10
    阿里面试:5000qps访问一个500ms的接口,如何设计线程池的核心线程数、最大线程数? 需要多少台机器?