安卓线程池理解

线程池的使用场景

在安卓开发中经常会遇到处理多张图片,或者分片上传等需要使用多线程的情况,如果简单的通过new Thread创建线程,会造成线程的频繁创建和销毁,占用大量的资源。并且频繁的调用GC机制,这会使性能降低,又非常耗时。

常见的线程池分类

最基本的ThreadPoolExecutor

1 通过构造方法,创建最基本的线程池,这也是参数最多,允许用户自己设置

ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(
        2,//核心线程数量
        4,//该线程池内最大线程数量
        100,//非核心线程保活时间
        TimeUnit.SECONDS,//非核心线程保活时间单位
        new LinkedBlockingDeque<Runnable>(2),//线程队列(队列中允许最大线程数量)
        new ThreadPoolExecutor.AbortPolicy()//线程数量超过限制时,拒绝策略。默认抛出异常
);

2 创建线程池之后,为了方便查看当前线程的信息,自定义一个线程

class MyThread implements Runnable {
        String name;
        public MyThread(String name) {
            this.name = name;
        }
        @Override
        public void run() {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            Log.e("syw","线程:"+Thread.currentThread().getName() +" 执行:"+name +"  run");
        }
    }

3 使用线程池的方法,执行多个任务

// 2个核心线程
// 6-2=4个任务将进入LinkedBlockingDeque队列,但是队列只能排进2个,所以新创建2个线程
// 核心线程数2+新创建的线程2如果超过线程池内最大线程数,在当前拒绝策略下会抛出异常
   for (int i = 0; i < 6; i++) {
       Log.e("syw","添加第"+i+"个任务");
       threadPoolExecutor.execute(new MyThread("线程"+i));
       Iterator iterator = threadPoolExecutor.getQueue().iterator();
       while (iterator.hasNext()){
           MyThread thread = (MyThread) iterator.next();
           Log.e("syw","列表:"+thread.name);
       }
   }

4 执行结果
在这里插入图片描述
5 结果分析

  • 线程池内核心线程数2,最大线程数4,队列中最大线程数量2
  • 先后顺序:核心线程、线程队列、创建新线程
  • 线程0和线程1直接分配核心线程执行,线程队列最大数量为2,所以线程2和线程3则需要添加到队列中排队。到线程4和线程5的时候,就需要另外创建非核心线程执行了。2个核心线程+2个非核心线程等于最大线程数4。此时如果for循环的数量是7的话,也就是说还需要创建3个非核心线程,此时会超出该线程池最大线程数,在当前的拒绝策略下,会抛出异常。

6 执行顺序
首先是核心线程1和核心线程2立刻执行线程0、线程1。
然后线程2、线程3进入队列,等待核心线程执行完成。
新创建的非核心线程3和非核心线程4立刻执行线程4、线程5
所以执行的顺序是0-1-4-5-2-3(线程的执行顺序是随机的0/1可能互换,4/5可能互换,2/3可能互换)
在这里插入图片描述

拒绝策略

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
 2,//核心线程数量
 4,//该线程池内最大线程数量
 100,//非核心线程保活时间
 TimeUnit.SECONDS,//非核心线程保活时间单位
 new LinkedBlockingDeque<Runnable>(2),//线程队列(队列中允许最大线程数量)
// new ThreadPoolExecutor.AbortPolicy()//默认策略。线程数量超过限制时,拒绝策略,抛出异常
// new ThreadPoolExecutor.DiscardPolicy()//线程数量超过限制时,丢掉多余任务
// new ThreadPoolExecutor.DiscardOldestPolicy()//线程数量超过限制时,丢掉先进入队列的任务
// new ThreadPoolExecutor.CallerRunsPolicy()//线程数量超过限制时,添加任务队列失败,主线程执行该任务。然后才会继续添加任务
);

如果线程数超过6(最大线程数4+队列最大值2)时

  • 第一种策略在添加第7个线程时,直接抛出异常
  • 第二种策略忽略第6个以后的线程,不抛异常
  • 第三种策略先移除队列中的第一个线程,然后在队列的尾部加入一个新线程。
  • 第四种策略相当于在线程池中加入了一个主线程,由主线程处理核心线程–线程队列–非核心线程之外的那一个任务。此时线程池中所有线程都被占用,不再继续添加任务。核心线程/非核心线程/主线程执行任务,当有线程执行完,线程队列中任务取出执行,后续的线程再加入队列。(只有当核心线程/非核心线程/队列都满的时候,主线程才会出来执行任务)
  • 第四种策略执行图例在这里插入图片描述
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值