Android使用ThreadPool

    线程池(ThreadPool):一种线程使用模式。

    What?不(什)知(么)所(东)谓(东)。那么首先我们得了解什么事线程,线程一般理解为我们顺序执行某一任务的最小执行单元,同一时间只做一件事情。而线程的创建和销毁在系统里面是有开销的,而且还比较大。

    我们来想想我们使用线程的方式一般为new Thread() 这样做是有很多弊端的,1、创建线程是有开销的 2、线程的生命周期不可控,容易引起内存泄漏  3、线程使用混乱,最后自己创建了多少线程不清楚,无法有效的维护。而线程池的目的就是帮我们有效的维护我们的线程,同时尽量减少线程的创建、销毁的开销。

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

 corePoolSize:核心线程池大小
maximumPoolSize:最大线程池大小
keepAliveTime:线程池最大空闲时间
unit:时间单位
workQueue:线程等待队列
threadFactory:线程创建工厂
handler:拒绝策略


我们可以用ThreadPoolExecutor来创建线程池,也可以用Executors的静态实现类创建我们的线程池。

1、Executors.newFixedThreadPool(N)
创建有N条核心线程没有非核心线程的线程池,核心线程不会被回收。当超过N数量的线程需排队等待前面线程执行完毕方可执行。

private void startTheadPool(){
        //通过Executors.newFixedThreadPool(N)创建的线程有N条固定数量线程的线程池,仅有核心线程且没有超时策略,线程不会被回收。
        //该方法创建的线程池没有非核心线程  当超过N数量的线程会等待前面线程执行完才会执行
        ExecutorService executorService = Executors.newFixedThreadPool(2);
        for (int i = 0; i < 10; i++){
            final int index = i;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                     Log.e(TAG,"CFixedThreadPool Start Run: 任务 = "+index+",线程 = "+Thread.currentThread().getName());
                    try {
                        Thread.sleep(2000);
                    }catch (InterruptedException e){

                    }
                }
            };
            executorService.execute(runnable);
        }
    }

执行结果如下:

2019-08-13 15:26:44.674 21796-21850/com.calm.cthreadpool E/CFixedThreadPool: CFixedThreadPool Start Run: 任务 = 0,线程 = pool-1-thread-1
2019-08-13 15:26:44.675 21796-21851/com.calm.cthreadpool E/CFixedThreadPool: CFixedThreadPool Start Run: 任务 = 1,线程 = pool-1-thread-2
2019-08-13 15:26:46.676 21796-21850/com.calm.cthreadpool E/CFixedThreadPool: CFixedThreadPool Start Run: 任务 = 2,线程 = pool-1-thread-1
2019-08-13 15:26:46.676 21796-21851/com.calm.cthreadpool E/CFixedThreadPool: CFixedThreadPool Start Run: 任务 = 3,线程 = pool-1-thread-2
2019-08-13 15:26:48.677 21796-21850/com.calm.cthreadpool E/CFixedThreadPool: CFixedThreadPool Start Run: 任务 = 4,线程 = pool-1-thread-1
2019-08-13 15:26:48.677 21796-21851/com.calm.cthreadpool E/CFixedThreadPool: CFixedThreadPool Start Run: 任务 = 5,线程 = pool-1-thread-2
2019-08-13 15:26:50.679 21796-21851/com.calm.cthreadpool E/CFixedThreadPool: CFixedThreadPool Start Run: 任务 = 7,线程 = pool-1-thread-2
2019-08-13 15:26:50.679 21796-21850/com.calm.cthreadpool E/CFixedThreadPool: CFixedThreadPool Start Run: 任务 = 6,线程 = pool-1-thread-1
2019-08-13 15:26:52.680 21796-21851/com.calm.cthreadpool E/CFixedThreadPool: CFixedThreadPool Start Run: 任务 = 9,线程 = pool-1-thread-2
2019-08-13 15:26:52.680 21796-21850/com.calm.cthreadpool E/CFixedThreadPool: CFixedThreadPool Start Run: 任务 = 8,线程 = pool-1-thread-1

可以看到一次执行了2条线程,而2秒之后待前2条线程执行完毕才继续执行下2条线程。而线程始终为线程池里的thread-1和thread-2。

2、Executors.newCachedThreadPool()

该方法创建的线程只有非核心线程,数量为无限大。没有核心线程。适合做一些量比较大但耗时较短的操作。

private void startTheadPool(){
        //CachedThreadPool是一种线程数量不定的线程池,只有非核心线程,线程数量为无限大。
        //比较适合做一些大量的耗时较少的任务
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++){
            final int index = i;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    Log.e(TAG,"CCachedThreadPool Start Run: 任务 = "+index+",线程 = "+Thread.currentThread().getName());
                    try {
                        Thread.sleep(2000);
                    }catch (InterruptedException e){

                    }
                }
            };
            executorService.execute(runnable);
        }
    }

执行结果如下:

2019-08-13 15:34:00.398 21796-22119/com.calm.cthreadpool E/CCachedThreadPool: CCachedThreadPool Start Run: 任务 = 0,线程 = pool-2-thread-1
2019-08-13 15:34:00.401 21796-22120/com.calm.cthreadpool E/CCachedThreadPool: CCachedThreadPool Start Run: 任务 = 1,线程 = pool-2-thread-2
2019-08-13 15:34:00.403 21796-22121/com.calm.cthreadpool E/CCachedThreadPool: CCachedThreadPool Start Run: 任务 = 2,线程 = pool-2-thread-3
2019-08-13 15:34:00.405 21796-22122/com.calm.cthreadpool E/CCachedThreadPool: CCachedThreadPool Start Run: 任务 = 3,线程 = pool-2-thread-4
2019-08-13 15:34:00.405 21796-22123/com.calm.cthreadpool E/CCachedThreadPool: CCachedThreadPool Start Run: 任务 = 4,线程 = pool-2-thread-5
2019-08-13 15:34:00.407 21796-22125/com.calm.cthreadpool E/CCachedThreadPool: CCachedThreadPool Start Run: 任务 = 6,线程 = pool-2-thread-7
2019-08-13 15:34:00.408 21796-22126/com.calm.cthreadpool E/CCachedThreadPool: CCachedThreadPool Start Run: 任务 = 7,线程 = pool-2-thread-8
2019-08-13 15:34:00.409 21796-22127/com.calm.cthreadpool E/CCachedThreadPool: CCachedThreadPool Start Run: 任务 = 8,线程 = pool-2-thread-9
2019-08-13 15:34:00.413 21796-22128/com.calm.cthreadpool E/CCachedThreadPool: CCachedThreadPool Start Run: 任务 = 9,线程 = pool-2-thread-10
2019-08-13 15:34:00.418 21796-22124/com.calm.cthreadpool E/CCachedThreadPool: CCachedThreadPool Start Run: 任务 = 5,线程 = pool-2-thread-6

我们可以看到基本在同一时刻执行了所有的线程,并且执行的线程均未重复。

3、Executors.newScheduledThreadPool(N)

该方法创建N条核心线程和不限制的非核心线程的线程池。一般来说,该线程池执行的为带有一定延迟或周期调度的线程任务。

private void startTheadPool(){
        //ScheduledExecutorService(N) 有N条核心线程且有非限制的非核心线程,非核心线程闲置时会被立即回收。
        //主要用于执行定时任务和具有固定周期的重复任务
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(2);
        for (int i = 0; i < 10; i++){
            final int index = i;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    Log.e(TAG,"CScheduleThreadPool Start Run: 任务 = "+index+",线程 = "+Thread.currentThread().getName());
                    try {
                        Thread.sleep(2000);
                    }catch (InterruptedException e){

                    }
                }
            };
            //延迟2秒执行runnable
            executorService.schedule(runnable,2000, TimeUnit.MILLISECONDS);
        }
    }

执行效果为线程开始后延迟2秒之后才开始真正的执行线程里的内容。除了延迟,其效果与FixedThreadPool执行效果类似。

4、Executors.newSingleThreadExecutor()

创建一个只有唯一线程的线程池。所有任务均顺序等待该唯一线程的执行。因为只有唯一线程,所以我们也不用去考虑线程通过的问题。

private void startTheadPool(){
        //SingleTheadExecutor只有一个核心线程,无非核心线程  所有任务都在一个线程里顺序执行 不需要线程同步
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        for (int i = 0; i < 10; i++){
            final int index = i;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    Log.e(TAG,"CSingleThreadExecutor Start Run: 任务 = "+index+",线程 = "+Thread.currentThread().getName());
                    try {
                        Thread.sleep(2000);
                    }catch (InterruptedException e){

                    }
                }
            };
            executorService.execute(runnable);
        }
    }

因为只有一个唯一线程,所以我们会每2秒执行一个任务,且线程名只有唯一的一个。看下验证结果。

2019-08-13 15:44:44.175 21796-22542/com.calm.cthreadpool E/CSingleThreadExecutor: CSingleThreadExecutor Start Run: 任务 = 0,线程 = pool-3-thread-1
2019-08-13 15:44:46.177 21796-22542/com.calm.cthreadpool E/CSingleThreadExecutor: CSingleThreadExecutor Start Run: 任务 = 1,线程 = pool-3-thread-1
2019-08-13 15:44:48.180 21796-22542/com.calm.cthreadpool E/CSingleThreadExecutor: CSingleThreadExecutor Start Run: 任务 = 2,线程 = pool-3-thread-1
2019-08-13 15:44:50.180 21796-22542/com.calm.cthreadpool E/CSingleThreadExecutor: CSingleThreadExecutor Start Run: 任务 = 3,线程 = pool-3-thread-1
2019-08-13 15:44:52.182 21796-22542/com.calm.cthreadpool E/CSingleThreadExecutor: CSingleThreadExecutor Start Run: 任务 = 4,线程 = pool-3-thread-1
2019-08-13 15:44:54.185 21796-22542/com.calm.cthreadpool E/CSingleThreadExecutor: CSingleThreadExecutor Start Run: 任务 = 5,线程 = pool-3-thread-1
2019-08-13 15:44:56.186 21796-22542/com.calm.cthreadpool E/CSingleThreadExecutor: CSingleThreadExecutor Start Run: 任务 = 6,线程 = pool-3-thread-1
2019-08-13 15:44:58.188 21796-22542/com.calm.cthreadpool E/CSingleThreadExecutor: CSingleThreadExecutor Start Run: 任务 = 7,线程 = pool-3-thread-1
2019-08-13 15:45:00.190 21796-22542/com.calm.cthreadpool E/CSingleThreadExecutor: CSingleThreadExecutor Start Run: 任务 = 8,线程 = pool-3-thread-1
2019-08-13 15:45:02.191 21796-22542/com.calm.cthreadpool E/CSingleThreadExecutor: CSingleThreadExecutor Start Run: 任务 = 9,线程 = pool-3-thread-1

可以看到与我们预判一致,没隔2秒执行一个任务,执行的线程名为thread-1

 

以上4种方式 就是我们线程池的常规使用方案,在实际项目中我们可以根据实际场景来择优使用。

示例相关代码:https://gitee.com/calm1516/CThreadPool.git

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值