android 线程池

线程池的好处

1.频繁的创建和销毁线程,会带来性能的问题。线程的创建和销毁都需要时间,当有大量的线程创建和销毁时,那么这些时间的消耗则比较明显,将导致性能上的缺失。
2.线程池方便管理线程,定时执行线程,间隔执行线程。线程池能控制线程的最大并发数量,避免大量抢占资源导致的阻塞现象。

ThreadPoorExecutor构造方法

threadPoolExecutor = new ThreadPoolExecutor(3,5,1, TimeUnit.SECONDS,new LinkedBlockingDeque(128));

 for (int i = 0; i < 30; i++) {
            final int finalI = i;
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    SystemClock.sleep(2000);
                    Log.e("ThreadPoolExecutor", "rune: " + finalI);
                    Log.e("ThreadPoolExecutor", Thread.currentThread().getName());

                }
            };
            threadPoolExecutor.execute(runnable);
}

corePoolSize:核心线程数,线程池正常情况下保持的线程数,大户人家“长工”的数量。
maximumPoolSize:最大线程数,当线程池繁忙时最多可以拥有的线程数,大户人家“长工”+“短工”的总数量。
keepAliveTime:空闲线程存活时间,没有活之后“短工”可以生存的最大时间。
TimeUnit:时间单位,配合参数 3 一起使用,用于描述参数 3 的时间单位。
BlockingQueue:线程池的任务队列,用于保存线程池待执行任务的容器。
ThreadFactory:线程工厂,用于创建线程池中线程的工厂方法,通过它可以设置线程的命名规则、优先级和线程类型。
RejectedExecutionHandler:拒绝策略,当任务量超过线程池可以保存的最大任务数时,执行的策略。

第一个参数corePoolSize 线程池中核心线程的数量,第二个参数maximumPoolSize 线程池中最大线程数量,
第三个参数keepAliveTime 非核心线程的超时时长,表示线程没有任务执行时最多保持多久时间会终止,第四个参数workQueue 线程池中的任务队列。

参数7:RejectedExecutionHandler

拒绝策略:当线程池的任务超出线程池队列可以存储的最大值之后,执行的策略。
默认的拒绝策略有以下 4 种:

AbortPolicy:拒绝并抛出异常。
CallerRunsPolicy:使用当前调用的线程来执行此任务。
DiscardOldestPolicy:抛弃队列头部(最旧)的一个任务,并执行当前任务。
DiscardPolicy:忽略并抛弃当前任务。
线程池的默认策略是 AbortPolicy 拒绝并抛出异常。

参数5:BlockingQueue

阻塞队列:线程池存放任务的队列,用来存储线程池的所有待执行任务。
它可以设置以下几个值:

ArrayBlockingQueue:一个由数组结构组成的有界阻塞队列。
LinkedBlockingQueue:一个由链表结构组成的有界阻塞队列。
SynchronousQueue:一个不存储元素的阻塞队列,即直接提交给线程不保持它们。
PriorityBlockingQueue:一个支持优先级排序的无界阻塞队列。
DelayQueue:一个使用优先级队列实现的无界阻塞队列,只有在延迟期满时才能从中提取元素。
LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。与SynchronousQueue类似,还含有非阻塞方法。
LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。
比较常用的是 LinkedBlockingQueue,线程池的排队策略和 BlockingQueue 息息相关。

ThreadPoorExecutor执行任务的顺序

(corePoolSize -> workQueue -> maximumPoolSize)

  1. 当未超过核心线程数时,就直接创建一个核心线程去执行任务。
  2. 当超过核心线程数,就将任务加入到workQueue的任务队列中等待
  3. 当任务队列中任务添满时候,在不超过最大线程数的情况下启动线程去处理任务
  4. 当线程数量超过最大线程数时,RejectedExecutionHandler对象通知调用者

Android中常用几种线程线程池

因为Java doc不建议直接使用ThreadPoorExecutor,Java提供了以下几种方式使用线程池,具体实现来看,它们底层实际上也是调用了 ThreadPoolExecutor,只不过参数都已配置好了。

一般以下的封装都不合适才会自己封装

一般需要根据任务的类型来配置线程池大小: 如果是 CPU 密集型任务,就需要尽量压榨 CPU,参考值可以设为 NCPU+1 ,
如果是 IO 密集型任务,参考值可以设置为 2*NCPU 当然,这只是一个参考值,
具体的设置还需要根据实际情况进行调整,比如可以 先将线程池大小设置为参考值,再观察任务运行情况和系统负载、资源利用率来 进行适当调整。

1 FixedThreadPool

核心线程数和最大线程数相同,一个无限的任务队列,就是说线程池一直有固定的线程数处理务。

  ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
  for (int i = 0; i < 30; i++) {
        final int finalI = i;
        Runnable runnable = new Runnable(){
            @Override
            public void run() {
                SystemClock.sleep(3000);
                Log.e("fixedThreadPool", "run: "+ finalI);
                Log.e("fixedThreadPool", Thread.currentThread().getName());

            }
        };
   fixedThreadPool.execute(runnable);

2 CachedThreadPool

没有核心线程,最大线程数为2^31-1,线程空闲60秒后被回收,任务队列SynchronousQueue是一个不存储的,所以这个线程的特点是只要任务一来,马上就有线程去执行。

  ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
   for (int i = 0; i < 30; i++) {
       final int finalI = i;
       Runnable runnable = new Runnable(){
           @Override
           public void run() {
               SystemClock.sleep(2000);
               Log.e("cachedThreadPool", "run: "+ finalI);
               Log.e("cachedThreadPool", Thread.currentThread().getName());                }
       };
   cachedThreadPool.execute(runnable);
  SystemClock.sleep(1000);

3 SingleThreadPool

线程池中只有一个核心线程,按顺序执行队列中的任务

   public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue()));
    }

4 ScheduledThreadPool

该线程最大的特点就可以延迟执行

//第一次延迟initialDelay秒,以后每次延迟delay秒执行一个任务
ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(3);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                Log.d("google_lenve_fb", "run: ----");
            }
        };
scheduledExecutorService.scheduleWithFixedDelay(runnable, 1, 1, TimeUnit.SECONDS);

线程池其他常用功能

1.shutDown() 关闭线程池,不影响已经提交的任务

2.shutDownNow() 关闭线程池,并尝试去终止正在执行的线程

3.allowCoreThreadTimeOut(boolean value) 允许核心线程闲置超时时被回收

4.submit 一般情况下我们使用execute来提交任务,但是有时候可能也会用到submit,使用submit的好处是submit有返回值

你可能感兴趣的:(android 线程池)