Android中的线程和线程池

来源:互联网 发布:淘宝联盟qq群推广技巧 编辑:程序博客网 时间:2024/06/06 01:56

一、Android中的线程

1.Android中的线程形态主要有三种,分别是AsyncTask、HandlerThread以及intentService。关于AsyncTask在上篇文章已经对他进行了详细的描述,这里就不再展开。详情可点击AsyncTask异步任务总结。


2.HandlerThread就是一种可以使用Handler的Thread,,它继承了Thread,它的实现就是在run方法中通过Looper.prepare()来创建消息队列,并通过Looper.loop()来开启消息循环,这样在实际的使用中就允许在HandlerThread中创建Handler了,外界可以通过Handler的消息方式通知HandlerThread执行一个具体的任务。HandlerThread的run方法是一个无限循环,因此当明确不需要再使用HandlerThread的时候,可以通过它的quit或者quitSafely方法来终止线程的执行。HandlerThread的最主要的应用场景就是用在IntentService中。


3.IntentService是一个继承自Service的抽象类,要使用它就要创建它的子类。IntentService适合执行一些高优先级的后台耗时任务,因为它是一种服务,所以它的优先级要比单纯的线程高很多。在实现上,它封装了HandlerThread和HAndler。下面是它的onCreate方法:

public void onCreate(){super.onCreate();HandlerThread thread = new HandlerThread("IntentService["+mName="]");thread.start();mServiceLooper = thread.getLooper()mServiceHandler = new ServicrHandler(mServiceLooper);}


可以看到在IntentService的onCreate方法中会创建HandlerThread,并使用HandlerThread的Looper来构造一个Handler对象ServiceHandler,这样通过ServiceHandler对象发送的消息最终都会在HandlerThread中执行。IntentService会将Intent封装到Message中,通过ServiceHandler发送出去,在ServiceHandler的handleMessage方法中会调用IntentService的抽象方法onHandleIntent,所以一般来讲我们使用IntentService就是在类中重写onHandlerIntent方法。

这就是Android中线程的三种主要形态了。


二、Android中的线程池

1.线程池的好处

(1)重用线程池中的线程,避免因为线程的创建和销毁所带来的性能开销。

(2)能有效控制线程池的最大并发数,避免因为大量的线程之间因为互相抢占系统资源而导致的阻塞现象。

(3)能够对线程进行简单的管理,并提供定时执行和指定间隔循环执行等功能。


2.ThreadPoolExecute是线程池的真正实现,ThreadPoolExecutor提供了一系列参数来配置线程池,通过不同的参数可以创建不同的线程池,Android的线程池都是通过Executors提供的工厂方法得到的。

以下是各个参数

(1)corePoolSize:核心线程数,默认情况下,核心线程会在线程中一直存活;
(2maximumPoolSize:最大线程数,当活动线程数达到这个数值后,后续的任务将会被阻塞;
(3keepAliveTime:非核心线程闲置时的超时时长,超过这个时长,闲置的非核心线程就会被回收;
4unit:用于指定keepAliveTime参数的时间单位,有TimeUnit.MILLISECONDS、TimeUnit.SECONDS、TimeUnit.MINUTES等;
5workQueue:任务队列,通过线程池的execute方法提交的Runnable对象会存储在这个参数中;
6threadFactory:线程工厂,为线程池提供创建新线程的功能。它是一个接口,它只有一个方法Thread newThread(Runnable r);
7RejectedExecutionHandler:当线程池无法执行新任务时,可能是由于任务队列已满或者是无法成功执行任务,这个时候就会调用这个Handler的rejectedExecution方法来通知调用者,默认情况下,rejectedExecution会直接抛出一个rejectedExecutionException。


3.ThreadPoolExecute的执行规则

(1)如果线程池中的线程数未达到核心线程的数量,那么会直接启动一个核心线程来执行任务;
(2)如果线程池中的线程数量已经达到或者超过核心线程的数量,那么任务会被插入到任务队列中排队等待执行;
(3)如果在步骤2中无法将任务插入到的任务队列中,可能是任务队列已满,这个时候如果线程数量没有达到规定的最大值,那么会立刻启动非核心线程来执行这个任务;
(4)如果步骤3中线程数量已经达到线程池规定的最大值,那么就拒绝执行此任务,ThreadPoolExecutor会调用RejectedExecutionHandler的rejectedExecution方法来通知调用者。


4.Android中常用的四种线程池

(1)FixedThreadPool:线程数量固定的线程池,它只有核心线程,且核心线程不会被回收。因此FixThreadExecutor可以快速响应外界请求。当所有的线程处于活动状态时,新任务处于等待状态,除非有线程空闲出来。
(2)CachedThreadPool:线程数量不固定的线程池(最大为Integer.MAX_VALUE),它只有非核心线程。当线程池中的线程都处于活动状态时,线程池会创建新的线程来执行新任务,否则就会利用空闲线程来执行新任务。空闲线程超过60秒就会被回收。因此它比较适合执行大量耗时较少的任务。
(3)ScheduledThreadPool:核心线程数量固定,非核心线程数量没有限制的线程池,主要用于执行定时任务和具有固定周期的任务,且当非核心线程闲置时立刻被回收。
(4)SingleThreadPool:只有一个核心线程的线程池,确保了所有的任务都在同一个线程中按顺序执行。


5.AsyncTask的THREAD_POOK_EXECUTOR线程池的配置

(1)corePoolSize=CPU核心数+1;
(2)maximumPoolSize=2倍的CPU核心数+1;
(3)核心线程无超时机制,非核心线程在闲置时间的超时时间为1s;
(4)任务队列的容量为128。


好了,关于Android中线程和线程池我的理解大致就是这些了。


0 0