一 进程与线程

进程:Android运转的最小单位,通常情况,一个Android应用拥有一个进程;特殊需求,如需单独开启新进程,可以通过android:process 属性开启新的进程;该属性可以声明到activity中,创建activity时默认开启单独的进程;

Android世界:android 线程池_第1张图片

 

 

 

线程:进程运行的最小单位;一个Application对应一个主线程,负责主要的UI操作;为防止出现ANR(Application not response),通常不在UI线程中进行耗时操作。网络请求、数据库处理、数据处理等操作,通常开辟新线程完成,也叫子线程。

 

线程创建的两种方式

继承Thread类;实现Runnable接口;

将待处理的代码逻辑置于run()方法中,通过start()方法执行子线程中的代码逻辑。

Android世界:android 线程池_第2张图片

 

 

 


二 线程池的引入

当多个子线程频繁使用时,会不断重复创建、运行、销毁线程,对性能造成一定的影响。合理利用线程池有以下优点:

第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。

第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。

第三:提高线程的可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控。


三 线程池创建的两种方式

1、使用未封装的ThreadPoolExecutor

Android世界:android 线程池_第3张图片

 

 

 

选取参数最多的构造方法进行解读:

public ThreadPoolExecutor(int corePoolSize,                          int maximumPoolSize,                          long keepAliveTime,                          TimeUnit unit,                          BlockingQueue workQueue,                          ThreadFactory threadFactory,                          RejectedExecutionHandler handler) 

 

Android世界:android 线程池_第4张图片

 

 

 

以下参数解读均参考https://blog.csdn.net/l540675759/article/details/62230562 一文:

corePoolSize--核心线程数。

默认情况下,核心线程数会在线程中一直存活,即使它们处于闲置状态。

但将ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true,那么核心线程就会存在超时策略,这个时间间隔由keepAliveTime所决定,当等待时间超过keepAliveTime所指定的时长后,核心线程就会被停止。

Android世界:android 线程池_第5张图片

 

 

 


maximumPoolSize --线程池所能容纳的最大线程数。

当活动线程数达到这个数值后,后续的新任务将会被阻塞。


keepAliveTime --非核心线程corePool闲置的超时时长。

超过这个时长,非核心线程就会被回收;当ThreadPoolExector的allowCoreThreadTimeOut属性设置为True时,keepAliveTime同样会作用于核心线程。


unit --用于指定keepAliveTime参数的时间单位。

这是一个枚举,常用的有TimeUnit.MILLISECONDS(毫秒)、TimeUnit.SECONDS(秒)以及TimeUnit.MINUTES(分钟)等。

TimeUnit.NANOSECONDS 纳秒

TimeUnit.MICROSECONDS 微秒

TimeUnit.MILLISECONDS 毫秒

TimeUnit.SECONDS  秒

TimeUnit.MINUTES  分钟

TimeUnit.HOURS   小时

TimeUnit.DAYS    天


workQueue --线程池中的任务队列。

通过线程池execute方法提交的Runnable对象会存储在这个参数中。

这个任务队列是BlockQueue类型,属于阻塞队列,就是当队列为空的时候,此时因为无任务可以被取出,该操作会被阻塞,等待任务加入队列中不为空的时候,才能进行取出操作;同理,在满队列的时候,添加操作同样会被阻塞。


threadFactory --线程工厂。

为线程池提供创建新线程的功能。ThreadFactory是一个接口,它只有一个方法,newThread(Runnable r),用来创建线程。

Android世界:android 线程池_第6张图片

 

 

 

2、使用封装后的 ExecutorService

JDK提供了完整的ExecutorService线程池,通过Executors创建符合需求的线程池;

Android世界:android 线程池_第7张图片

 

 

 

由ExecutorService对线程池进行管理;

Android世界:android 线程池_第8张图片

 

 

 

Executor将runnable对象execute()到容器中进行代码执行。

Android世界:android 线程池_第9张图片

 

 

 


类图及解读如下,取自https://www.cnblogs.com/whx20100101/p/9862392.html:

Android世界:android 线程池_第10张图片

 

 

 

类图解读:

①ExecutorService 接口继承了Executor 接口,是Executor 的子接口;

  ②Executor接口中定义了execute()方法,用来接收一个Runnable接口的对象,

  而ExecutorService接口中定义的submit()方法可以接收Runnable和Callable接口对象;

  ③Executor接口中execute()方法不返回任何结果,而ExecutorService接口中submit()方法可以通过一个 Future 对象返回运算结果。

  ④Executor和ExecutorService除了允许客户端提交一个任务,ExecutorService 还提供用来控制线程池的方法。  比如:调用 shutDown() 方法终止线程池。

  ⑤Executors 类提供工厂方法用来创建不同类型的线程池。比如: 

   newCachedThreadPool()创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

newSingleThreadExecutor() 创建一个只有一个线程的线程池,

  newFixedThreadPool(int numOfThreads)来创建固定线程数的线程池,

   newScheduledThreadPool(int corePoolSize) 创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

 

四 常见的4类具有不同功能特性的线程池及其适用场景

1、newCachedThreadPool

创建一个可缓存的线程池。如果线程池的大小超过了处理任务所需要的线程,那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时,此线程池又可以智能的添加新线程来处理任务。此线程池不会对线程池大小做限制,线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。

Android世界:android 线程池_第11张图片

 

 

 

适用范围:

①当整个线程都处于闲置状态时,线程池中的线程都会超时而被停止,这时候的CacheThreadPool几乎不占任何系统资源的;

②执行很多短期异步的小程序或者负载较轻的服务器


2、FixedThreadPool

一种数量固定的线程池,当线程处于空闲的时候,并不会被回收,除非线程池被关闭;当所有的线程都处于活动状态时,新任务都会处于等待状态,直到有线程空闲出来。

由于FixedThreadPool中只有核心线程并且这些核心线程不会被回收,这意味着它能够更加快速地响应外界的请求;通过构造方法可以看出,FixedThreadPool只有核心线程,并且超时时间为0(即无超时时间),所以不会被回收.

Android世界:android 线程池_第12张图片

 

 

 

适用范围:执行长期的任务,性能会好很多


3、newScheduledThreadPool

创建一个固定大小的线程池,线程池内线程存活时间无限制,线程池可以支持定时及周期性任务执行,如果所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue队列中,这是一种按照超时时间排序的队列结构

适用范围:主要用于执行定时任务和具有固定周期的重复任务。


4、SingleThreadExecutor

创建只有一个线程的线程池,且线程的存活时间是无限的;当该线程正繁忙时,对于新任务会进入阻塞队列中(无界的阻塞队列)

适用范围:一个任务一个任务执行的场景


附录:

线程池任务执行流程:

  1. 当线程池小于corePoolSize时,新提交任务将创建一个新线程执行任务,即使此时线程池中存在空闲线程。
  2. 当线程池达到corePoolSize时,新提交任务将被放入workQueue中,等待线程池中任务调度执行
  3. 当workQueue已满,且maximumPoolSize>corePoolSize时,新提交任务会创建新线程执行任务
  4. 当提交任务数超过maximumPoolSize时,新提交任务由RejectedExecutionHandler处理
  5. 当线程池中超过corePoolSize线程,空闲时间达到keepAliveTime时,关闭空闲线程
  6. 当设置allowCoreThreadTimeOut(true)时,线程池中corePoolSize线程空闲时间达到keepAliveTime也将关闭

取自:https://www.cnblogs.com/sachen/p/7401959.html

更多相关文章

  1. Android测量View宽和高的一般通用方法
  2. 实用Android studio gradle的离线安装方法(官方)
  3. android中退出当前应用程序的四种方法
  4. Android截屏截图方法所有方法汇总(包括Activity、View、ScrollVie
  5. 关于getting 'android:label' attribute: attribute is not a st
  6. Android原生代码调用H5 Web网页中的Javascript函数方法
  7. Android 反编译apk 到java源码的方法

随机推荐

  1. Android(安卓)Map开发基础知识学习笔记
  2. Android系统升级的完整过程
  3. Android(安卓)入门第八讲02-WebView的高
  4. ImageView、Bitmap的属性android:scaleTy
  5. add study URL
  6. Android软键盘-弹起时布局向上拉-登录界
  7. Android(安卓)SDK下载和更新失败的解决方
  8. 在Android上编译OSG[3.0.2 ]
  9. 【Android自学笔记】android实现TextView
  10. Android避免OOM(内存优化)