• Android-线程池


    线程池

    技术点

    1.自定义线程池
    2.ThreadPoolExecutor
    3.设计模式工作线程
    4.fork/join线程池

    异步模式之工作线程

      让有限的工作线程轮流异步处理无限多的任务,也可以归为分工模式,典型实现就是线程池,也体现了经典设计模式中的享元模式。
      注意:不同任务类型应该使用不同的线程池,这样能够避免饥饿现象,且效率上得到合理的分配
      线程饥饿现象:本是上是出现多任务混合在同一个线程池中,如果出现相互影响的状况出现类似死锁的问题,有相互关联的相关任务不作为同一线程池处理,而是单独开辟线程池

    享元设计模式

      本质:运用内存共享的原理,去有效支撑大量的细颗粒度的对象
      享元工厂,一个享元工厂,用来创建并管理对象,他主要是用来确保合理地共享对象,当用户请求一个对象时,由工厂提供一个已创建的对象示例或者创建一个
      享元对象:一个重复的对象
      使用场景:如果一个程序对于某个对象进行大量应用,且使用生命周期短,可以考虑采取享元模式进行复用。

    线程数量与核心数

    处理器核数:
      线程核心数是一种执行资源,资源数量就是核的个数,应用程序的线程就是服务请求数,而操作系统的作用如何调配有限的资源来服务更多的请求,这就是进程调度的概念,一般情况下,服务线程相对公平的分配到核上运行,并且在时间片上轮流使用,这就是所谓的并发执行。
      比如系统是4核,如果3个线程,分配到3个核上,8哥线程,每个核分配两个线程执行,10个线程,有些核跑3个,有些跑两个。
      所以,并非线程数量越大,速度越快,线程数量太过于庞大会导致各种内存问题,因为一个线程的开辟还会涉及到线程的上下文的应用。

    问题:创建多少线程合适?
      CPU密集型运算:通常采用CPU核数+1能够实现最优的CPU利用率,+1是保证当线程由于缺页时故障或其他原因导致暂停,额外的这个线程能够顶上去,保证CPU始终周期不被浪费。

    I/O密集型运算:
      CPU不总是处于繁忙状态,例如,当你执行业务计算时,这时候会使用CPU资源,但当你执行IO操作,或者远程的RPC调用时,包括进行数据库操作等,这个时候CPU会闲下来,你可以利用多线程提高他的利用率。

    经验公式如下:
      线程数=核数 * 期望CPU利用率 * 总时间(CPU计算时间+等待时间)/CPU计算时间例如:4核CPU,计算时间时50%,其他等待时间是50%,期望CPU被100%利用,套用公式4*100%*100%/50%=8

    ThreadPoolExecutor

    public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue< Runnatle > workQueue, ThreadFactory threadFactory, RejectedExecutionMandler handler)

      corePoolSize核心线程数目
      maximumPoolSize最大线程数目
      keepAliveTime生存时间-针对救急线程
      workQueue阻塞队列
      threadFactory线程工厂,可以为线程创建时起个好名字
      handler拒绝策略

    在这里插入图片描述
      maxSize最大线程 - coreSize核心线程 = 救急线程
      核心线程可以1个执行1个等待,当来第5个任务的时候就会扩,产生急救线程。

    在这里插入图片描述
      利用位运算合并整型变量在并发下的意义:如果两个数都是原子变量,那么合并之后,只需要对于一个原子进行CAS操作,而不是两个CAS操作

    JDK中的拒绝策略

    ThreadPoolExecutor自己已经提供了4个拒绝策略:
      CallerRunsPolicy:在任务被拒绝添加后,会调用当前线程池的所在的线程去执行被拒绝的任务,这个策略的缺点就是可能阻塞主线程。
      AbortPolicy:默认的拒绝策略就是AbortPolicy,直接抛出异常,抛出个RejectedExecutionException异常,也不执行这个任务了
      DiscardPolicy:这个东西什么都没干
      DiscardOldestPolicy:当任务被拒绝添加时,会抛弃任务队列中最旧的任务也就是最先加入队列的,再把这个新任务添加进去。

    ThreadPoolExecutor与当前自定义的区别

    1.救急线程
      性能提升
    2.状态设置
      对于线程池的管理
    3.原子合并
      利用位运算进行CAS的优化
    4.工厂模式的应用

    fork/join线程池

      fork/join时JDK1.7后加入的新的线程池实现,他主要体现的是分治思想,适用于能够进行任务拆分的CPU密集型运算,他是为了处理大数据诞生的,所谓任务拆分,是将一个大任务拆分为算法上相同的小任务,直至不能够拆分可以直接求解,跟递归相关的一些计算,如归并排序,斐波那契数列,都可以进行分治完成,fork/join在分治的基础中加入了多线程,可以把每个任务的分解和合并交给不同的线程来完成,进一步提升运算效率,fork/join默认会创建于CPU核心数大小相同的线程池,最常见业务,对于文件夹的操作。

  • 相关阅读:
    STA -- clock gating check
    系统架构师备考倒计时18天(每日知识点)
    195基于matlab的凸轮机构GUI界面
    flutter系列之:深入理解布局的基础constraints
    JavaWeb实现文件上传和下载
    6.网络编程套接字(上)
    推荐几个好用的国内AI网站
    URL编码解码详解
    【深度学习之模型优化】模型剪枝、模型量化、知识蒸馏概述
    使用Blazor WebAssembly整合PocketBase的基础项目模板
  • 原文地址:https://blog.csdn.net/weixin_43580319/article/details/126198458