内容简介:在操作系统中,线程是操作系统调度的最小单元,同时线程又是一种受限的系统资源,即线程不可能无限制地产生,并且线程的创建和销毁都会有相应的开销。在 Android 中除了 Thread 以外,还有 AsyncTask、IntentService 以及 HandlerThread 都扮演着线程的角色。在 Java 中默认情况下一个进程只有一个线程,这个就是主线程,除主线程以外的线程都叫子线程,Android 沿用了同样的线程模型。AsyncTask 中有两个线程池(SerialExecutor 和 THREAD
在操作系统中,线程是操作系统调度的最小单元,同时线程又是一种受限的系统资源,即线程不可能无限制地产生,并且线程的创建和销毁都会有相应的开销。在 Android 中除了 Thread 以外,还有 AsyncTask、IntentService 以及 HandlerThread 都扮演着线程的角色。
主线程和子线程
在 Java 中默认情况下一个进程只有一个线程,这个就是主线程,除主线程以外的线程都叫子线程,Android 沿用了同样的线程模型。
Android 中的线程形态
AsyncTask
- AsyncTask 是一个轻量级的异步任务类,在线程池中执行后台任务,然后把进度和最终结果传递到主线程更新 UI。
-
AsyncTask 是一个抽象的泛型类,提供了
Params
、Progress
和Result
三个泛型参数。如果不需要传递具体的参数,参数类型可以使用Void
来代替。public abstract class AsyncTask <Params, Progress, Result>
-
AsyncTask 提供 4 个核心方法:
- onPreExecute() :在主线程中执行,一般用于做一些准备工作。
- doInBackground(Params… params) :在线程池中执行异步任务,params 为输入参数。在此方法中可以调用
publishProgress(Progress)
方法来更新任务进度。最终需要返回结果给onPostExecute
方法。 - onProgressUpdate(Progess… values) :在主线程中执行,任务进度更新时会调用此方法。
- onPostExecute(Result result) :在主线程中执行,result 为异步任务中返回的结果。
- AsyncTask 使用时的注意点:
- AsyncTask 的类必须在主线程中加载,这一过程在 Android 4.1 及以上版本被系统自动完成(ActivityThread 的
main
方法会调用 AsyncTask 的init
方法)。 - AsyncTask 的对象必须在主线程中创建。
-
execute
方法必须在 UI 线程中调用。 - 不要在程序中直接调用
onPreExecute
、onPostExecute
、doInBackground
和onProgressUpdate
方法。 - 一个 AsyncTask 对象只能执行一次,即只能调用一次
execute
方法,否则会报错。 - 在 Android 1.6 之前,AsyncTask 是串行执行任务的,Android 1.6 的时候开始采用线程池处理并行任务,但是从 Android 3.0 开始,又换回了串行执行任务的方式,不过我们可以通过
executeOnExecutor
方法执行并行任务。
- AsyncTask 的类必须在主线程中加载,这一过程在 Android 4.1 及以上版本被系统自动完成(ActivityThread 的
AsyncTask 的工作原理
AsyncTask 中有两个线程池(SerialExecutor 和 THREAD_POOL_EXECUTOR)和一个 Handler(InternalHandler)。其中线程池 SerialExecutor 用于任务的排队,而线程池 THREAD_POOL_EXECUTOR 用于真正地执行任务,InternalHandler 用于将执行环境从线程池切换到主线程。
HandlerThread
- HandlerThread 继承了 Thread,它是一种可以使用 Handler 的 Thread。
- HandlerThread 的实现就是在其
run
方法中通过Looper.prepare()
来创建消息队列,通过Looper.loop()
来开启消息循环。 - HandlerThread 的
run
方法是一个无限循环,当不需要使用时,要通过quit
或者quitSafely
方法来终止线程。 - HandlerThread 的一个典型使用场景就是 IntentService。
IntentService
-
IntentService 是一种特殊的抽象 Service,内部封装了 HandlerThread 和 Handler,比较适合执行一些高优先级的后台任务,不容易被杀死。
@Override public void onCreate() { super.onCreate(); HandlerThread thread = new HandlerThread("IntentService[" + mName + "]"); thread.start(); mServiceLooper = thread.getLooper(); mServiceHandler = new ServiceHandler(mServiceLooper); }
-
IntentService 调用
stopSelf(int startId)
方法来尝试停止服务,会等待所有消息都处理完毕后才真正终止服务。 - IntentService 的执行顺序是按外界发起的顺序去执行的。
Android 中的线程池
- 线程池的优点:
- 重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。
- 能有效控制线程池的最大并发数,避免大量线程之间因互相抢占系统资源而导致的阻塞现象。
- 能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。
- Android 中线程池的概念源于 Java 中的 Executor,真正实现为 ThreadPoolExecutor。
ThreadPoolExecutor
ThreadPoolExecutor 常用构造方法如下:
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)
- corePoolSize :线程池的核心线程数,默认情况下核心线程会一直存活。如果将 ThreadPoolExecutor 的
allowCoreThreadTimeOut
属性设置为 true,闲置时间超过 keepAliveTime 会被终止。 - maximumPoolSize :线程池所能容纳的最大线程数(核心线程 + 非核心线程),当活动线程数达到这个数值后,后续任务会被阻塞。
- keepAliveTime :非核心线程闲置时的超时时长,超过这个时长,非核心线程会被回收。当 ThreadPoolExecutor 的
allowCoreThreadTimeOut
属性设置为 true 时,同样作用于核心线程。 - unit :指定 keepAliveTime 参数的时间单位。
- workQueue :线程池中的任务队列,通过线程池的
execute
方法提交的 Runnable 对象会被存储在这个参数中。 - threadFactory :线程工厂,为线程池提供创建新线程的功能。
ThreadPoolExecutor 执行任务时大致遵循如下规则:
- 如果线程池中的线程数量未达到核心线程的数量,那么会直接启动一个核心线程来执行任务。
- 如果线程池中的线程数量达到或超过核心线程的数量,那么任务会被插入任务队列等待执行。
- 如果步骤2中无法将任务插入任务队列中,这往往是由于任务队列已满,这时如果线程数量未到达线程池规定的最大值,那么会立即启动一个非核心线程来执行任务。
- 如果步骤3中的线程数量已经达到了线程池规定的最大值,那么就会拒绝执行此任务。
线程池的分类
Android 中最常见的四类线程池都是通过 Executors 的静态方法创建的。
-
FixedThreadPool- 线程数量固定的线程池,只有核心线程
public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); }
-
CachedThreadPool- 线程数量不固定的线程池,只有非核心线程
public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); }
-
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()); }
-
SingleThreadExecutor- 只有一个核心线程的线程池,确保了所有的任务都在同一个线程中按顺序执行
public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- java中线程安全,线程死锁,线程通信快速入门
- ObjC 多线程简析(一)-多线程简述和线程锁的基本应用
- Java多线程之线程中止
- iOS 多线程之线程安全
- java多线程 线程安全问题
- Java 多线程(二)—— 线程的同步
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Scrum精髓
Kenneth Rubin / 姜信宝、米全喜、左洪斌、(审校)徐毅 / 清华大学出版社 / 2014-6-1 / CNY 79.00
短短几年时间,Scrum跃升为敏捷首选方法,在全球各地得以普遍应用。针对如何用好、用巧这个看似简单的框架,本书以通俗易懂的语言、条理清晰的脉络阐述和提炼出Scrum的精髓。全书共4部分23章,阐述了七大核心概念:Scrum框架,敏捷原则,冲刺,需求和用户故事,产品列表,估算与速率,技术债;三大角色:产品负责人,ScrumMaster,开发团队以及Scrum团队构成:Scrum规划原则及四大规划活动......一起来看看 《Scrum精髓》 这本书的介绍吧!