Android线程池

2022-05-18  本文已影响0人  人世看客

一、为什么要用线程池

目前就我在Android开发工作中,实际自己写线程用到线程池真的很少,但是又不得不去了解下线程池。线程池直白点就是管理线程的一个工具,平时我们创建子线程可能直接用Thread方法创建一个子线程就完事了。

Thread{
   //需要执行的耗时代码
}.start()

当然,如果是简单的单线程,不需要使用线程池的。牵扯多线程时推荐试用线程池,比如我们常见的多个文件同时下载。会牵扯到多个线程创建执行,如果处理不好,会导致大量线程创建和销毁,这样会造成资源浪费,使性能降低。这时候就需要用到线程池去管理线程

二、线程池原理

线程池是一个池子,里面能容纳多个线程。线程池帮助我们管理线程的创建、复用、销毁;具体啥时候创建,何时复用,什么时候销毁;需要根据ThreadPoolExecutor类的构造参数去实现

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), defaultHandler);
    }

参数说明:

下面代码是一个实例:

 val threadPoolExecutor =
            ThreadPoolExecutor(2, 4, 1, TimeUnit.SECONDS, LinkedBlockingQueue<Runnable>(6))
        findViewById<View>(R.id.btn5).setOnClickListener{
            for (i in 1..10) {
                threadPoolExecutor.execute{
                    Thread.sleep(3000)
                    Log.e("print","当前线程个数:$i, 线程名:${Thread.currentThread().name}")
                }
            }
        }

核心线程数为2,最大线程数为4,超时1秒,任务队列长度6个。任务总数10个
注意:这里有个公式(任务队列总数 + 最大线程数 >= 任务总数),这个公式必须成立,不然会报错java.util.concurrent.RejectedExecutionException

运行结果:

log1

等待几秒再运行for循环中代码打印日志

log2

分析日志1:
一共10个任务,程序会先创建2个核心线程去领2个任务执行,还剩下8个任务。而任务队列长度只有6,还有剩余两个任务没法放入,这时候就会创建非核心线程去执行这两个任务(这里允许最大线程数为4,已经创建了2个核心线程,刚好还可以创建2个非核心线程,也就是我前面说的那个公式必须成立,如果这里最大线程数小于4,就会报错)。看日志刚好一共创建了4条线程,后面的都是复用这4条线程去执行

分析日志2:
因为等待了几秒,超过了我们设置的超时时间1秒。线程池会回收两个非核心线程。从日志可以看出线程1和3被回收了(非核心线程),复用了线程2和4(核心线程),然后又创建了两个新的线程5和6

三、介绍几种常见线程池

几种方式底层都是实现ThreadPoolExecutor构造参数

上一篇下一篇

猜你喜欢

热点阅读