前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android 四种常见的线程池

Android 四种常见的线程池

作者头像
xiangzhihong
发布2018-02-05 14:39:14
6530
发布2018-02-05 14:39:14
举报
文章被收录于专栏:向治洪向治洪

引入线程池的好处

1)提升性能。创建和消耗对象费时费CPU资源

2)防止内存过度消耗。控制活动线程的数量,防止并发线程过多。

我们来看一下线程池的简单的构造

代码语言:javascript
复制
public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {...}

使用上面的方式创建线程池的话,我们需要配置一堆东西,非常麻烦,所以我们不建议这么使用。而是推荐使用Executors的工厂方法来创建线程池,Executors类是官方提供的一个工厂类,它里面封装好了众多功能不一样的线程池。下面就介绍几个常用的线程池。

代码语言:javascript
复制
public ThreadPoolExecutor(  
//核心线程数,除非allowCoreThreadTimeOut被设置为true,否则它闲着也不会死  
int corePoolSize,   
//最大线程数,活动线程数量超过它,后续任务就会排队                     
int maximumPoolSize,   
//超时时长,作用于非核心线程(allowCoreThreadTimeOut被设置为true时也会同时作用于核心线程),闲置超时便被回收             
long keepAliveTime,                            
//枚举类型,设置keepAliveTime的单位,有TimeUnit.MILLISECONDS(ms)、TimeUnit. SECONDS(s)等  
TimeUnit unit,  
//缓冲任务队列,线程池的execute方法会将Runnable对象存储起来  
BlockingQueue<Runnable> workQueue,  
//线程工厂接口,只有一个new Thread(Runnable r)方法,可为线程池创建新线程  
ThreadFactory threadFactory)

1、FixedThreadPool() :

该方法返回一个固定线程数量的线程池,该线程池中的线程数量始终不变,即不会再创建新的线程,也不会销毁已经创建好的线程,自始自终都是那几个固定的线程在工作,所以该线程池可以控制线程的最大并发数。 栗子:假如有一个新任务提交时,线程池中如果有空闲的线程则立即使用空闲线程来处理任务,如果没有,则会把这个新任务存在一个任务队列中,一旦有线程空闲了,则按FIFO方式处理任务队列中的任务。

代码语言:javascript
复制
public static ExecutorService newFixThreadPool(int nThreads){  
    return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());  
}  
//使用  
Executors.newFixThreadPool(5).execute(r);  

2、CachedThreadPool() :

该方法返回一个可以根据实际情况调整线程池中线程的数量的线程池。即该线程池中的线程数量不确定,是根据实际情况动态调整的。 栗子:假如该线程池中的所有线程都正在工作,而此时有新任务提交,那么将会创建新的线程去处理该任务,而此时假如之前有一些线程完成了任务,现在又有新任务提交,那么将不会创建新线程去处理,而是复用空闲的线程去处理新任务。那么此时有人有疑问了,那这样来说该线程池的线程岂不是会越集越多?其实并不会,因为线程池中的线程都有一个“保持活动时间”的参数,通过配置它,如果线程池中的空闲线程的空闲时间超过该“保存活动时间”则立刻停止该线程,而该线程池默认的“保持活动时间”为60s。

代码语言:javascript
复制
public static ExecutorService newCachedThreadPool(int nThreads){  
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit. SECONDS, new SynchronousQueue<Runnable>());  
}  
//使用  
Executors.newCachedThreadPool().execute(r);  

3、SingleThreadExecutor() :

该方法返回一个只有一个线程的线程池,即每次只能执行一个线程任务,多余的任务会保存到一个任务队列中,等待这一个线程空闲,当这个线程空闲了再按FIFO方式顺序执行任务队列中的任务。

代码语言:javascript
复制
public static ExecutorService newSingleThreadPool (int nThreads){  
    return new FinalizableDelegatedExecutorService ( new ThreadPoolExecutor (1, 1, 0, TimeUnit. MILLISECONDS, new LinkedBlockingQueue<Runnable>()) );  
}  
//使用  
Executors.newSingleThreadPool ().execute(r); 

4、ScheduledThreadPool() :

该方法返回一个可以控制线程池内线程定时或周期性执行某任务的线程池。

代码语言:javascript
复制
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize){  
return new ScheduledThreadPoolExecutor(corePoolSize);  
}  
public ScheduledThreadPoolExecutor(int corePoolSize){  
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS, new DelayedQueue ());  
}  
//使用,延迟1秒执行,每隔2秒执行一次Runnable r  
Executors. newScheduledThreadPool (5).scheduleAtFixedRate(r, 1000, 2000, TimeUnit.MILLISECONDS); 

自定义线程池

Android中常用的线程池就上面的四种,其实在Java中还有一种常见的线程池(newSingleThreadScheduledExecutor),其实上面的线程池对于我们开发已经是足够了,不过有时候上面的仍然不能满足我们,这时候我们就需要自定义不同功能的线程池。上面我们也说了线程池功能的不同归根到底还是内部的BlockingQueue实现不同,所以,我们要实现我们自己相要的线程池,就必须从BlockingQueue的实现上做手脚。

那么我们接下来就用PriorityBlockingQueue来实现一个FIFO的线程池。

1)创建一个基于PriorityBlockingQueue的线程池

代码语言:javascript
复制
ExecutorService priorityThreadPool = new ThreadPoolExecutor(3,3,0L,TimeUnit.SECONDS,new PriorityBlockingQueue());

2)创建一个实现Runnable接口的类,并向外提供我们实现自定义功能,并实现Comparable接口

代码语言:javascript
复制
public abstract class PriorityRunnable implements Runnable, Comparable {
    private int priority;
 
    public PriorityRunnable(int priority) {
        if (priority 0)
            throw new IllegalArgumentException();
        this.priority = priority;
    }
 
    @Override
    public int compareTo(PriorityRunnable another) {
        int my = this.getPriority();
        int other = another.getPriority();
        return my 1 : my > other ? -1 : 0;
    }
 
    @Override
    public void run() {
        doSth();
    }
 
    public abstract void doSth();
 
    public int getPriority() {
        return priority;
    }
}

3)使用PriorityRunnable提交任务

代码语言:javascript
复制
ExecutorService priorityThreadPool = new ThreadPoolExecutor(3, 3, 0L, TimeUnit.SECONDS, new PriorityBlockingQueue());
        for (int i = 1; i 10; i++) {
            final int priority = i;
            priorityThreadPool.execute(new PriorityRunnable(priority) {
                @Override
                public void doSth() {
                    String threadName = Thread.currentThread().getName();
                    Log.v("zxy", "线程:" + threadName + ",正在执行优先级为:" + priority + "的任务");
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016-10-19 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 引入线程池的好处
  • 1、FixedThreadPool() :
  • 2、CachedThreadPool() :
  • 3、SingleThreadExecutor() :
  • 自定义线程池
    • 1)创建一个基于PriorityBlockingQueue的线程池
      • 2)创建一个实现Runnable接口的类,并向外提供我们实现自定义功能,并实现Comparable接口
        • 3)使用PriorityRunnable提交任务
        相关产品与服务
        对象存储
        对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档