线程池android,线程池拒绝策略有哪些

Android线程池的使用

在Android中有主线程和子线程的区分。主线程又称为UI线程,主要是处理一些和界面相关的事情,而子线程主要是用于处理一些耗时比较大的一些任务,例如一些网络操作,IO请求等。如果在主线程中处理这些耗时的任务,则有可能会出现ANR现象(App直接卡死)。

吉安网站建设公司创新互联,吉安网站设计制作,有大型网站制作公司丰富经验。已为吉安成百上千提供企业网站建设服务。企业网站搭建\外贸网站制作要多少钱,请找那个售后服务好的吉安做网站的公司定做!

线程池,从名字的表明含义上我们知道线程池就是包含线程的一个池子,它起到新建线程、管理线程、调度线程等作用。

既然Android中已经有了线程的概念,那么为什么需要使用线程池呢?我们从两个方面给出使用线程池的原因。

在Android中线程池就是ThreadPoolExecutor对象。我们先来看一下ThreadPoolExecutor的构造函数。

我们分别说一下当前的几个参数的含义:

第一个参数corePoolSize为 核心线程数 ,也就是说线程池中至少有这么多的线程,即使存在的这些线程没有执行任务。但是有一个例外就是,如果在线程池中设置了allowCoreThreadTimeOut为true,那么在 超时时间(keepAliveTime) 到达后核心线程也会被销毁。

第二个参数maximumPoolSize为 线程池中的最大线程数 。当活动线程数达到这个数后,后续添加的新任务会被阻塞。

第三个参数keepAliveTime为 线程的保活时间 ,就是说如果线程池中有多于核心线程数的线程,那么在线程没有任务的那一刻起开始计时,如果超过了keepAliveTime,还没有新的任务过来,则该线程就要被销毁。同时如果设置了allowCoreThreadTimeOut为true,该时间也就是上面第一条所说的 超时时间 。

第四个参数unit为 第三个参数的计时单位 ,有毫秒、秒等。

第五个参数workQueue为 线程池中的任务队列 ,该队列持有由execute方法传递过来的Runnable对象(Runnable对象就是一个任务)。这个任务队列的类型是BlockQueue类型,也就是阻塞队列,当队列的任务数为0时,取任务的操作会被阻塞;当队列的任务数满了(活动线程达到了最大线程数),添加操作就会阻塞。

第六个参数threadFactory为 线程工厂 ,当线程池需要创建一个新线程时,使用线程工厂来给线程池提供一个线程。

第七个参数handler为 拒绝策略 ,当线程池使用有界队列时(也就是第五个参数),如果队列满了,任务添加到线程池的时候的一个拒绝策略。

可以看到FixedThreadPool的构建调用了ThreadPoolExecutor的构造函数。从上面的调用中可以看出FixedThreadPool的几个特点:

可以看到CacheThreadPool的构建调用了ThreadPoolExecutor的构造函数。从上面的调用中可以看出CacheThreadPool的几个特点:

可以看到ScheduledThreadPoolExecutor的构建调用了ThreadPoolExecutor的构造函数。从上面的调用中可以看出ScheduledThreadPoolExecutor的几个特点:

可以看到SingleThreadExecutor的构建调用了ThreadPoolExecutor的构造函数。从上面的调用中可以看出SingleThreadExecutor的几个特点:

第十一章 Android的线程和线程池

执行AsyncTask的execute方法,会执行executeOnExecutor方法,该方法第一个参数是线程池,第二个是传给AsyncTask的参数

在该方法里,首先会调用onPreExecute方法,然后将传进来的参数赋值给mWorker.params,再调用第一个参数线程池的execute方法,传入mFuture

如果是AsyncTask的默认线程池SerialExecutor,则只是用于排队,使AsyncTask提交的任务一个一个的执行。最终执行是放在THREAD_POOL_EXECUTER线程池中执行的

执行mFuture的run方法,最终调用mWorker对象的call方法,在call方法里,会执行doInBackground方法,返回一个Result对象,传入postResult方法里

在postResult方法里,会利用sHandler即主线程的handler把Result发送到主线程进行处理,在handler的handMessage方法中,会调用onPostExecute方法,将结果发送到主线程

如果需要更新进度,可在doInBackground方法里调publishProgress方法,传入进度信息,publishProgress方法里就会通过sHandler把进度信息传到主线程

Android中的线程池

线程池的好处

1、重用线程池中的线程,避免线程的创建与销毁带来的性能开销

2、能有效控制线程池的最大并发数,避免大量线程因抢占资源而导致的阻塞

3、能对线程进行简单的管理,提供定时或者指定间隔时间、循环执行等操作

线程池的概率来自于java的Executor接口,实现类是ThreadPoolExecutor, 它提供一系列的参数来配置线程池,以此构建不同的线程池。Android的线程池分4类,都是通过Executors所提供的工厂方法来得到。

ThreadPoolExecutor有四个构造函数,下面这个是最常用的

public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueueRunnnable workQueue, ThreadFactory threadFactory)

corePoolSize

线程池中的核心线程数,默认情况下核心线程会在线程池中一直存活,即使他们处于闲置状态。如果设置ThreadPoolExecutor 中的allowCoreThreadTimeOut = true, 核心线程在等待新任务到来时有超时机制,时间超过keepAliveTime所指定的时间后,核心线程会终止。

maximumPoolSize

最大线程数

keepAliveTime

非核心线程闲置的超时时间,超过这个时间,非核心线程会被回收。核心线程则要看allowCoreThreadTimeOut属性的值。

unit

时间单位

workQueue

线程池中的工作队列

threadFactory

线程工厂,为线程池提供创建新线程的功能。

举个例子,我们常用的okhttp内部也是使用了线程池,它的ThreadPoolExecutor主要是定义在Dispatcher类里面。 使用的是CachedThreadPool。

executorService = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS, SynchronousQueue(), ThreadFactory("okhttp Dispatcher", false))

1、FixedThreadPool

通过Executors的newFixedThreadPool()创建,这是一个线程数量固定的线程池,里面所有的线程都是核心线程。

public static ExecutorService newFixedThreadPool(int nThreads){

return new ThreadPoolExecutor(nThreads, nThreads, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueueRunnable())

}

2、CachedThreadPool

通过Executors的newCacheThreadPool()创建,这是一个线程数量不定的线程池,里面所有的线程都是非核心线程。最大线程数是无限大,当线程池中的线程都处于活动状态时,新的task会创建新的线程来处理,否则就使用空闲的线程处理,所有的线程都是60s的超时时间,超时后会自动回收。

public static ExecutorService newFixedThreadPool(){

return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueueRunnable())

}

3、ScheduledThreadPool

通过Executors的newScheduledThreadPool()创建, 核心线程固定,非核心线程无限大,当非核心线程空闲时,会立即被回收。适合做定时任务或者固定周期的重复任务。

public static ExecutorService newScheduledThreadPool(int corePoolSize){

return new ThreadPoolExecutor(corePoolSize, Integer.MAX_VALUE, 0, TimeUnit.SECONDS, new DelayedWorkQueue())

}

4、SingleThreadExcecutor

通过Executors的newSingleThreadPool()创建,内部只有一个核心线程。

public static ExecutorService newFixedThreadPool(){

return new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueueRunnable())

}

课外知识:LinkedBlockingQueue

LinkedBlockingQueue是由链表组成的阻塞队列,内部head 指向队列第一个元素,last指向最后一个元素。入队和出队都会加锁阻塞,都是使用了不同的锁。

DelayedWorkQueue

延时队列,队内元素必须是Delayed的实现类。对内元素会按照Delayed时间进行排序,对内元素只有在delayed时间过期了才能出队。

入队的时候不阻塞队列,出队的时候,如果队列为空或者队列里所有元素都等待时间都没有到期,则该线程进入阻塞状态。

Android中的线程和线程池

一、除了Thread外,扮演线程角色的还有:AsyncTask和IntentService,同时HandlerThread也扮演特殊的线程。

  IntentService:内部采用HandlerThread来执行,像一个后台线程,同时是一个服务,不容易被系统杀死。

二、HandlerThread的run方法是一个无限循环

三、IntentService中任务是排队执行的

四、AsyncTask 

1、Android1.6之前串行执行任务,1.6时候采用线程池里的并行,Android3.0开始又开始串行(为了避免并发错误),单任可以并行。

2、AsyncTask必须在UI线程调用(不过这个不是绝对的,和版本有关系,API 16之前,API 16到 22, API 22以后) 参考一

原因:内部有静态Handler,采用UI线程的Looper来处理消息,这就是为什么AsyncTask必须在UI线程调用,因为子线程默认没有Looper无法创建下面的Handler,程序会直接Crash

3、AsyncTask中有两个线程池和一个Handler,一个线程池用于任务排队,一个线程池用于真正的执行任务,InternalHandler用于将

执行环境从线程池切换到主线程

AsyncTask串行与并行

五、线程池

线程池中多余的线程是如何回收的


当前文章:线程池android,线程池拒绝策略有哪些
标题来源:http://hbruida.cn/article/hopcho.html