Android中线程池的使用分析

引言:

说起线程池,学习过Java基础的同学估计都不陌生,Android中的线程池其实就是java的线程池。那么为什么线程池名声这么大,当然有其独特之处。这就引来了线程池到底有何优势。

线程池的优势:

  1. Android中像访问内存卡,联网等耗时较长的任务时,需要在异步线程中进行,所以需要新开线程进行。但创建或者销毁线程伴随着系统的开销,频繁的创建和销毁线程,会较大的影响系统的性能。使用线程池,可用已有的闲置线程来执行新任务。
  2. 我们知道线程能共享系统资源,如果同时执行的线程过多,就有可能导致系统资源不足而产生阻塞的情况,运用线程池能有效的控制线程最大并发数,避免以上的问题。
  3. 线程池能够对线程进行有效的管理,比如延时执行,定时定周期循环执行等。

线程池ThreadPoolExecutor

既然线程池有这些优势,那么我们就要考虑怎样使用它。还是那句话,一个有追求的青年,要追根溯源。

Android中的线程池来源于java中的线程池,那么我们就分析一下:

java中线程池的概念是一个接口,Excutor;其中ThreadPoolExecutor是这个接口的具体实现,也就是说线程池的所有定义及大部分操作将会从这个ThreadPoolExecutor中进行逻辑处理。那么我们就去看一下ThreadPoolExecutor的具体实现。

ThreadPoolExecutor的四个构造函数:

`
// 第一种构造器
public ThreadPoolExecutor(int corePoolSize, 
                        int maximumPoolSize, 
                        long keepAliveTime, 
                        TimeUnit unit,
                     BlockingQueue<Runnable> workQueue) {
    throw new RuntimeException("Stub!");
}

// 第二种构造器
public ThreadPoolExecutor(int corePoolSize, 
                        int maximumPoolSize, 
                        long keepAliveTime,
                     TimeUnit unit, 
                    BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
    throw new RuntimeException("Stub!");
}

// 第三种构造器
public ThreadPoolExecutor(int corePoolSize, 
                        int maximumPoolSize, 
                        long keepAliveTime, 
                        TimeUnit unit, 
                        BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
    throw new RuntimeException("Stub!");
}

// 第四种构造器
public ThreadPoolExecutor(int corePoolSize, 
                        int maximumPoolSize, 
                        long keepAliveTime, 
                        TimeUnit unit, 
                        BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
    throw new RuntimeException("Stub!");
}`

看到这些构造函数的参数是不是一脸懵逼,不要急不要慌,其实搞明白第一种构造函数就可以了其他三个都是鸡肋。下面我们就详细的分析一下这些参数。


1. corePoolSize:核心线程数
线程池新建线程的时候,如果当前线程总数小于corePoolSize,则新建的是核心线程,如果超过corePoolSize,则新建的是非核心线程;核心线程会一直保留,即使处于空闲状态,要想隔一段时间销毁它,必须指定ThreadPoolExecutor的allowCoreThreadTimeOut这个属性为true。
2. maximumPoolSize:线程池中线程的最大数
最大数 = 核心线程数 + 非核心线程数;其中非核心线程就是在线程池中的核心线程已满,但线程总数小于最大数时创建的线程为费核心线程。
3. keepAliveTime: 非核心线程保留时长
当非核心线程空闲时间超过保留时长时,就会被销毁掉。
4. TimeUnit:keepAliveTime的单位,TimeUnit是一个枚举类型

public enum TimeUnit {
            DAYS,
            HOURS,
            MICROSECONDS,
            MILLISECONDS,
            MINUTES,
            NANOSECONDS,
            SECONDS;
    }

5 BlockingQueue
线程池中的任务队列:维护着等待执行的Runnable对象;当所有的核心线程都在干活时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心线程执行任务。

其他的两个参数基本不用,需要详细了解的可以自行查看源码。

ThreadPoolExecutor的具体使用

认识完ThreadPoolExecutor,接下来就看一下怎样使用。其实很简单;

① new ThreadPoolExecutor对象,参数自行配置
② 使用对象调用execute方法,方法里传入runnable接口
③ 上②的runnable接口就是需要执行的任务

经过上面三步就完成了一个任务的添加执行。

常见的四种线程池对象

我们牛逼的Google攻城狮给我们封装了四种常用的线程池对象,就是对ThreadPoolExecutor进行不同参数进行详细配置的具体实现。当然我们也可以按照上述三步走进行自定义ThreadPoolExecutor线程池。但一般情况这四种线程池足够我们使用。

  1. CachedThreadPool():
    直接从源码中寻找答案:
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                            60L, TimeUnit.SECONDS, 
                    new SynchronousQueue<Runnable>());
}
从上述源码可以看出可缓存线程池的特点:
① 线程数无限制
② 没有核心线程,都是非核心线程

使用方法:
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();

2 . FixedThreadPool():定长线程池
源码:

public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                  0L,TimeUnit.MILLISECONDS,
        new LinkedBlockingQueue<Runnable>());
}
特点:①:可控制线程最大并发数(线程数固定)
     ②:超出的线程会在队列中等待

使用方法:

ExecutorService fixedThreadPool = Executors.newFixedThreadPool(int nThreads);

3 . ScheduledThreadPool():定时和周期性线程池
4 . SingleThreadExecutor():单一线程池
① 有且仅有一个工作线程执行任务
② 所有任务按照指定顺序执行,即遵循队列的入队出队规则

感谢
关于线程池的这篇文章参考(_liuzh)和(SEU_Calvin)的博客,感谢他们无私的分享。

———————————END BUT FINAL——————————-

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值